This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.

Try executing this chunk by clicking the Run button within the chunk or by placing your cursor inside it and pressing Cmd+Shift+Enter.

options(scipen = 999)
library(tidyverse)
library(ggplot2)
library(plotly)
library(data.table)
library(lubridate)
library(dplyr)
library(corrplot)
library(leaflet)
#Get only the Summary data for some initial analysis

summary_raw_data<-read_csv ('data/claim_summary_v1.csv' )
Parsed with column specification:
cols(
  .default = col_double(),
  esco_id = col_character(),
  bene_hic_num = col_character(),
  claim_first_dialysis_date = col_character(),
  claim_last_dialysis_date = col_character()
)
See spec(...) for full column specifications.
summary_wds<-summary_raw_data
#Get the data with all the required fields for analysis
#claim_detail_raw_data<-fread("data/claim_details.csv",sep = "|",fill = T)

#detail_raw_data<-read_csv ('data/claim_details.csv' )
locations<-read_csv('data/ESCo_LOCATIONS_lo.csv' )
Parsed with column specification:
cols(
  location_id = col_character(),
  short_name = col_character(),
  location_address_1 = col_character(),
  location_address_2 = col_character(),
  location_city = col_character(),
  location_state = col_character(),
  location_zip_code = col_double(),
  latitude = col_double(),
  longitude = col_double()
)

INITIAL ANALYSIS WITH THE SUMMARY DATA ONLY.


summary_wds %>% 
  select (-esco_id,-bene_hic_num,-esco_aligned_flag) %>% 
  filter(patient_id == '811454') %>% 
  arrange(dos_year,dos_month)
NA
str(summary_wds)
Classes ‘spec_tbl_df’, ‘tbl_df’, ‘tbl’ and 'data.frame':    10364 obs. of  35 variables:
 $ esco_id                  : chr  "E0050" "E0050" "E0050" "E0050" ...
 $ bene_hic_num             : chr  "161446232A" "161446232A" "161446232A" "161480276A" ...
 $ patient_id               : num  811454 811454 811454 814249 814249 ...
 $ dos_year                 : num  2018 2018 2018 2017 2017 ...
 $ dos_month                : num  1 8 11 2 5 1 4 4 2 8 ...
 $ claim_first_dialysis_date: chr  "2018-01-03 00:00:00.000" "2018-08-01 00:00:00.000" "2018-11-02 00:00:00.000" "2017-02-01 00:00:00.000" ...
 $ claim_last_dialysis_date : chr  "2018-01-31 00:00:00.000" "2018-08-31 00:00:00.000" "2018-11-30 00:00:00.000" "2017-02-06 00:00:00.000" ...
 $ dci_claims               : num  1 0 0 1 1 1 1 1 1 0 ...
 $ non_dci_claims           : num  3 7 11 3 1 1 6 67 1 3 ...
 $ payment                  : num  2512 2853 3498 2272 2617 ...
 $ part_a                   : num  2053 2323 2160 2068 2432 ...
 $ part_b_phys              : num  459 530 1300 204 185 ...
 $ part_b_dme               : num  0 0 39.1 0 0 ...
 $ inpatient                : num  0 0 0 0 0 ...
 $ outpatient_dialysis      : num  2053 2323 2160 2068 2432 ...
 $ outpatient_er            : num  0 0 0 0 0 ...
 $ outpatient_other         : num  0 0 0 0 0 ...
 $ hha                      : num  0 0 0 0 0 0 0 0 0 0 ...
 $ snf                      : num  0 0 0 0 0 ...
 $ hospice                  : num  0 0 0 0 0 0 0 0 0 0 ...
 $ full_encounter           : num  0 0 0 0 0 0 0 0 0 0 ...
 $ phys_neph                : num  222 222 222 185 185 ...
 $ phys_hosp                : num  0 0 0 0 0 ...
 $ phys_ed                  : num  0 0 0 0 0 ...
 $ vasc_access              : num  0 0 916 0 0 ...
 $ ambulance                : num  0 0 0 0 0 ...
 $ phys_other               : num  236.9 307.9 162.1 19.2 0 ...
 $ dme                      : num  0 0 39.1 0 0 ...
 $ esco_aligned_flag        : num  1 1 1 1 1 1 1 1 1 1 ...
 $ inpatient_fluid          : num  0 0 0 0 0 0 0 0 0 0 ...
 $ outpatient_er_fluid      : num  0 0 0 0 0 0 0 0 0 0 ...
 $ part_a_other_fluid       : num  0 0 0 0 0 0 0 0 0 0 ...
 $ inpatient_access         : num  0 0 0 0 0 0 0 0 0 0 ...
 $ outpatient_er_access     : num  0 0 0 0 0 0 0 0 0 0 ...
 $ part_a_other_access      : num  0 0 0 0 0 0 0 0 0 0 ...
 - attr(*, "spec")=
  .. cols(
  ..   esco_id = col_character(),
  ..   bene_hic_num = col_character(),
  ..   patient_id = col_double(),
  ..   dos_year = col_double(),
  ..   dos_month = col_double(),
  ..   claim_first_dialysis_date = col_character(),
  ..   claim_last_dialysis_date = col_character(),
  ..   dci_claims = col_double(),
  ..   non_dci_claims = col_double(),
  ..   payment = col_double(),
  ..   part_a = col_double(),
  ..   part_b_phys = col_double(),
  ..   part_b_dme = col_double(),
  ..   inpatient = col_double(),
  ..   outpatient_dialysis = col_double(),
  ..   outpatient_er = col_double(),
  ..   outpatient_other = col_double(),
  ..   hha = col_double(),
  ..   snf = col_double(),
  ..   hospice = col_double(),
  ..   full_encounter = col_double(),
  ..   phys_neph = col_double(),
  ..   phys_hosp = col_double(),
  ..   phys_ed = col_double(),
  ..   vasc_access = col_double(),
  ..   ambulance = col_double(),
  ..   phys_other = col_double(),
  ..   dme = col_double(),
  ..   esco_aligned_flag = col_double(),
  ..   inpatient_fluid = col_double(),
  ..   outpatient_er_fluid = col_double(),
  ..   part_a_other_fluid = col_double(),
  ..   inpatient_access = col_double(),
  ..   outpatient_er_access = col_double(),
  ..   part_a_other_access = col_double()
  .. )
summary(summary_wds)
   esco_id          bene_hic_num         patient_id        dos_year      dos_month      claim_first_dialysis_date claim_last_dialysis_date   dci_claims     non_dci_claims     payment         
 Length:10364       Length:10364       Min.   : 30111   Min.   :2017   Min.   : 1.000   Length:10364              Length:10364             Min.   :0.0000   Min.   :  0.0   Min.   :    34.18  
 Class :character   Class :character   1st Qu.:798197   1st Qu.:2017   1st Qu.: 4.000   Class :character          Class :character         1st Qu.:1.0000   1st Qu.:  3.0   1st Qu.:  2664.22  
 Mode  :character   Mode  :character   Median :806827   Median :2018   Median : 7.000   Mode  :character          Mode  :character         Median :1.0000   Median :  6.0   Median :  3284.65  
                                       Mean   :711615   Mean   :2018   Mean   : 6.521                                                      Mean   :0.9818   Mean   : 11.7   Mean   :  6916.75  
                                       3rd Qu.:812964   3rd Qu.:2018   3rd Qu.: 9.000                                                      3rd Qu.:1.0000   3rd Qu.: 14.0   3rd Qu.:  6039.45  
                                       Max.   :910902   Max.   :2018   Max.   :12.000                                                      Max.   :5.0000   Max.   :138.0   Max.   :139204.35  
     part_a           part_b_phys        part_b_dme         inpatient      outpatient_dialysis outpatient_er     outpatient_other       hha              snf             hospice       
 Min.   :    13.17   Min.   :    0.0   Min.   :    0.00   Min.   :     0   Min.   :   0        Min.   :    0.0   Min.   :    0.0   Min.   :   0.0   Min.   :    0.0   Min.   :   0.00  
 1st Qu.:  2321.80   1st Qu.:  224.9   1st Qu.:    0.00   1st Qu.:     0   1st Qu.:2037        1st Qu.:    0.0   1st Qu.:    0.0   1st Qu.:   0.0   1st Qu.:    0.0   1st Qu.:   0.00  
 Median :  2730.59   Median :  369.4   Median :    0.00   Median :     0   Median :2323        Median :    0.0   Median :    0.0   Median :   0.0   Median :    0.0   Median :   0.00  
 Mean   :  5898.76   Mean   :  957.7   Mean   :   60.23   Mean   :  2601   Mean   :2299        Mean   :  106.7   Mean   :  391.9   Mean   : 160.5   Mean   :  323.2   Mean   :  16.37  
 3rd Qu.:  4754.09   3rd Qu.: 1002.8   3rd Qu.:    4.33   3rd Qu.:     0   3rd Qu.:2609        3rd Qu.:    0.0   3rd Qu.:  115.2   3rd Qu.:   0.0   3rd Qu.:    0.0   3rd Qu.:   0.00  
 Max.   :131619.23   Max.   :22145.9   Max.   :17581.02   Max.   :131619   Max.   :7283        Max.   :26135.5   Max.   :25749.6   Max.   :9011.7   Max.   :22185.7   Max.   :7032.21  
 full_encounter   phys_neph       phys_hosp          phys_ed         vasc_access     ambulance        phys_other            dme           esco_aligned_flag inpatient_fluid   outpatient_er_fluid
 Min.   :0      Min.   :  0.0   Min.   :    0.0   Min.   :   0.00   Min.   :   0   Min.   :   0.0   Min.   :    0.00   Min.   :    0.00   Min.   :1         Min.   :    0.0   Min.   :   0.000   
 1st Qu.:0      1st Qu.:180.8   1st Qu.:    0.0   1st Qu.:   0.00   1st Qu.:   0   1st Qu.:   0.0   1st Qu.:   17.26   1st Qu.:    0.00   1st Qu.:1         1st Qu.:    0.0   1st Qu.:   0.000   
 Median :0      Median :213.8   Median :    0.0   Median :   0.00   Median :   0   Median :   0.0   Median :  111.42   Median :    0.00   Median :1         Median :    0.0   Median :   0.000   
 Mean   :0      Mean   :189.0   Mean   :  259.2   Mean   :  28.58   Mean   :  75   Mean   : 100.7   Mean   :  305.26   Mean   :   60.23   Mean   :1         Mean   :  197.4   Mean   :   7.179   
 3rd Qu.:0      3rd Qu.:220.4   3rd Qu.:    0.0   3rd Qu.:   0.00   3rd Qu.:   0   3rd Qu.:   0.0   3rd Qu.:  309.44   3rd Qu.:    4.33   3rd Qu.:1         3rd Qu.:    0.0   3rd Qu.:   0.000   
 Max.   :0      Max.   :877.3   Max.   :10036.4   Max.   :1007.74   Max.   :5523   Max.   :8815.2   Max.   :16197.08   Max.   :17581.02   Max.   :1         Max.   :42387.0   Max.   :4956.360   
 part_a_other_fluid inpatient_access outpatient_er_access part_a_other_access
 Min.   :    0.00   Min.   :    0    Min.   :    0.00     Min.   :    0.00   
 1st Qu.:    0.00   1st Qu.:    0    1st Qu.:    0.00     1st Qu.:    0.00   
 Median :    0.00   Median :    0    Median :    0.00     Median :    0.00   
 Mean   :   36.26   Mean   :  281    Mean   :   14.89     Mean   :   92.67   
 3rd Qu.:    0.00   3rd Qu.:    0    3rd Qu.:    0.00     3rd Qu.:    0.00   
 Max.   :14684.18   Max.   :92109    Max.   :11694.69     Max.   :15409.49   
summary(summary_wds$payment)
     Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
    34.18   2664.22   3284.65   6916.75   6039.45 139204.35 
summary_wds %>% 
  ggplot(aes(x=payment)) +
  geom_histogram(breaks = seq(500,100000,by=1000),
                 bins=20,
                 col="red",
                 fill = "green",
                 alpha = 0.2) +
 scale_x_log10()  +
  labs(x="Payments", y = "Counts",title = "Payments Histogram")  

change_increase<-summary_wds %>% select (patient_id,payment,dos_year,dos_month) %>% group_by(patient_id,dos_year,add=TRUE) %>% summarise(sum_payment = sum(payment), num_of_months = NROW(dos_month)) %>% ungroup %>% filter(num_of_months >11) %>% arrange (num_of_months,patient_id,dos_year,desc(sum_payment))

change_increase\(patient_id <- as.factor(change_increase\)patient_id)

change_increase %>% filter (patient_id == ‘403675’)

change_increase\(patient_id <- as.factor(change_increase\)patient_id ) change_increase\(dos_year <- as.factor(change_increase\)dos_year)

pl <- ggplot( change_increase,aes(y=sum_payment, x = patient_id ,fill=dos_year)) + geom_bar(stat = “identity”,position = ‘dodge’) + labs(x=“patient_id”, y= “Payments”) + ggtitle(“yearly payments difference for patients”)

pl

#pivot the data and understand hte percentage change in payments and get expensive patients expensive_patients<-pivot_wider(change_increase, names_from = dos_year, values_from = sum_payment, values_fill = list(sum_payment = 0)) %>% mutate(percent_change = (2018-2017)/2017 * 100) %>% filter(percent_change > 50 & 2017 != 0) %>% arrange (desc(percent_change))

expensive_patients

summary_wds %>% 
  filter(patient_id =='798094') %>% 
  arrange (dos_year,dos_month)
NA
library(dplyr)
year_plot<- summary_wds %>% 
  group_by(dos_year,dos_month) %>% 
  summarise(sum_pay = sum(payment)) %>% 
  ungroup()  
year_plot

year_plot$dos_month <- as.factor(year_plot$dos_month)
year_plot$dos_year <- as.factor(year_plot$dos_year)

pl <- ggplot( year_plot,aes(y=sum_pay, x = dos_month ,fill=dos_year)) +
  geom_bar(stat = "identity",position = 'dodge') +
  labs(x="Months", y= "Payments") +
  ggtitle("Increase in Payments from 2017 to 2018")


pl

NA
#redo this with non summarize raw data

plbox <- ggplot(year_plot,aes(y=sum_pay, x = dos_month,fill=dos_month) )+
  geom_boxplot() +
  labs(x="Months", y= "Payments") +
  ggtitle("Distribution of Payments by Months") +
  theme_dark()
       
plbox

NA

#redo this with non summarize raw data

 dci_data_ws %>% 
         select(patient_id,modality,payment) %>% 
         filter(modality =='HIC') %>%      
         arrange(desc(payment))  %>% 
         head(n = 30) %>% 
         ggplot(aes(x=reorder(patient_id,payment),y=payment,fill=patient_id))+
         geom_bar(stat="identity") +
         coord_flip() +
         labs(x="Patient ID",
              y="Payments",
              title = "Top 30 patients with high payments")

NA
NA
NA
NA
NA
NA
NA

Add a new chunk by clicking the Insert Chunk button on the toolbar or by pressing Cmd+Option+I.

When you save the notebook, an HTML file containing the code and output will be saved alongside it (click the Preview button or press Cmd+Shift+K to preview the HTML file).

The preview shows you a rendered HTML copy of the contents of the editor. Consequently, unlike Knit, Preview does not run any R code chunks. Instead, the output of the chunk when it was last run in the editor is displayed.

summary_2017<-summary_wds %>% 
  group_by(dos_month,dos_year) %>% 
  summarise(
            total_patients = NROW(patient_id),
            totalpayments = sum(payment),
            min_pay = min(payment),
            max_pay = max(payment),
            avg_pay = sum(payment)/NROW(patient_id)) %>% 
  ungroup() %>%
  arrange(dos_year,dos_month) %>% 
  filter(dos_year =="2017")

summary_2017
summary_2017_pivot <- summary_2017 %>% 
                      pivot_longer(min_pay:avg_pay, names_to = "payment_type", values_to = "payment")

summary_2017_pivot$dos_month = as.factor(summary_2017_pivot$dos_month)

summary_2017_pivot
NA
 
pl<- ggplot(summary_2017_pivot,aes(x=dos_month, y = payment, fill = payment_type)) +
      geom_col(stat = "identity",position = 'dodge') +
      geom_hline(yintercept = 6000, linetype = "dashed",color = "darkred") +
      labs(x="Months", y = "Payments") +
      ggtitle("2017 minimum, maximum and average payments")
Ignoring unknown parameters: stat
pl + scale_y_continuous(breaks = seq(0,130000,5000))

NA
NA
all_payments<-summary_wds %>% 
  group_by(dos_month) %>% 
  summarise(
            total_patients = NROW(patient_id),
            totalpayments = sum(payment),
            min_pay = min(payment),
            max_pay = max(payment),
            avg_pay = sum(payment)/NROW(patient_id)) %>% 
  ungroup() %>% 
  pivot_longer(min_pay:avg_pay, names_to='payment_type',values_to = 'payments')

all_payments
#redo  with box plot

pl_all<- ggplot(all_payments,aes(x=dos_month, y = payments, fill = payment_type)) +
      geom_col(stat = "identity",position = 'dodge') +
      scale_x_continuous(name ="Months",breaks = seq(1,12,1)) +
      geom_hline(yintercept = 6000, linetype = "dashed",color = "darkred") +
      labs(x="Months", y = "Payments") +
      ggtitle("Minimum, Maximum and Average payments")
Ignoring unknown parameters: stat
  
pl_all + scale_y_continuous(breaks = seq(0,130000,5000))

ANALYSIS USING SUMMARY AND DETAIL DATA Get the data and clean it

#get detail and summary data and save it in a df
detail_raw_data<-read_csv ('data/claim_details.csv' )
Duplicated column names deduplicated: 'patient_id' => 'patient_id_1' [37]Parsed with column specification:
cols(
  .default = col_double(),
  esco_id = col_character(),
  bene_hic_num = col_character(),
  claim_first_dialysis_date = col_character(),
  claim_last_dialysis_date = col_character(),
  location_id = col_character(),
  start_date = col_datetime(format = ""),
  end_date = col_datetime(format = ""),
  esrd_date = col_datetime(format = ""),
  modality = col_character(),
  hgb_cutoff = col_character(),
  epo_ceiling = col_character(),
  route_freq = col_character(),
  drug_name = col_character(),
  ferritin_cutoff = col_character(),
  tsat_cutoff = col_character(),
  sup_name = col_character(),
  tx_epo = col_character(),
  venofer_given = col_character(),
  venofer_wasted = col_character(),
  ferrlecit_given = col_character()
  # ... with 42 more columns
)
See spec(...) for full column specifications.
1 parsing failure.
 row       col   expected actual                     file
7272 esrd_date date like    NULL 'data/claim_details.csv'
dci_data<-detail_raw_data

dci_data<-dci_data %>%
select(-esco_id,-bene_hic_num,-full_encounter,-phys_neph,-phys_hosp,-phys_ed,-ambulance,-phys_other,-esco_aligned_flag,-inpatient_fluid,-outpatient_er_fluid,-part_a_other_fluid,-patient_id_1,-dos_yyyy,-dos_mm,-esrd_date,-hgb_date,-tsat_date,-ferr_date,-albumin_date,-pth_date,-ca_date,-cca_date,-ph_date,-k_date,-urr_date,-ktv_date,-epo_given,-venofer_wasted,-inpatient_access,-outpatient_er_access,-part_a_other_access,-dci_claims,-non_dci_claims,-hha,-hospice,-dme,-start_date,-end_date,-epo_ceiling,-route_freq,-drug_name,-ferritin_cutoff,-tsat_cutoff,-hgb_cutoff,-ferrlecit_wasted,-zemplar_iv_wasted,-calcijex_iv_wasted,-feraheme_wasted,-hectorol_iv_wasted,-tx_missed,-sensipar_dispensed)

#make sure all the columns are in correct data types.

#change claims date columns to date datatype
date_columns <- c("claim_first_dialysis_date","claim_last_dialysis_date")
dci_data[date_columns] <- lapply(dci_data[date_columns],as.Date)

#change the other columns to factor
fac_columns <- c("patient_id","dos_year","location_id","dos_month","modality","tx","tx_epo","sup_name")
dci_data[fac_columns] <- lapply(dci_data[fac_columns],as.factor)

#change the below columns to logical
bool_columns <- c("epo_protocol_flag","iron_protocol_flag","nutsup_protocol_flag","hgb_exclude_flag","active_flag")
dci_data[bool_columns] <- lapply(dci_data[bool_columns],as.logical)
 
#Make below colums as logical true if they have any value else if they have null make it logical false.
dci_data<-dci_data %>% 
  mutate_at(vars("ferrlecit_given","feraheme_given","venofer_given","zemplar_iv_given","hectorol_iv_given","calcijex_iv_given","zemplar_or_given","hectorol_or_given","calcijex_iv_given","zemplar_or_given","hectorol_or_given","calcijex_or_given","activase_given","prostat_given","nepro_given","liquacel_given","has_catheter","aranesp_given","protinex_given","mircera_given","sensipar_given","parsabiv_given","protein_bar_given",
                 "ice_cream_given","gelatein_given"),
            funs(case_when(.=="NULL" ~ FALSE,
                                 TRUE ~ TRUE)))

#FIRST make the null VALUES in char col to zero's except for date columns

num_columns <- c("hgb","tsat","ferr","albumin","pth","ca","cca","ph","k","urr","ktv","tx_epo")
dci_data[num_columns]<-dci_data[num_columns]%>% 
                            replace(.=="NULL","0") 

#change all the character columns ot numeric
dci_data<-dci_data %>% mutate_if(is.character,as.numeric)
 
#names(dci_data)
 
#as for date columns we cannot replace na values ot 0. first make them character columns and then make rest to the na values to 0 in entire dataframe
dci_data$claim_first_dialysis_date <-as.character.Date(dci_data$claim_first_dialysis_date )
dci_data$claim_last_dialysis_date <-as.character.Date(dci_data$claim_last_dialysis_date )
 
#make all na values to 0 in entire dataframe
 dci_data[is.na(dci_data)]<-0
# sum(is.na(dci_data))

 #making the dates column back to date datatype
dci_data$claim_first_dialysis_date <- as.Date(dci_data$claim_first_dialysis_date)
dci_data$claim_last_dialysis_date <- as.Date(dci_data$claim_last_dialysis_date)

#delete the outliers( payments which are less than 1500)
dci_data<-dci_data %>% 
  filter(`payment`>1500) %>% 
  arrange(desc(payment))

#combine 2 separate part_b payments to one
dci_data<-dci_data %>% 
  mutate(part_b = part_b_phys + part_b_dme)

#save to RDS file
dci_data_ws<- dci_data
saveRDS(dci_data_ws,file="DCI_midcourse/data/dci_data.rds")
library(dplyr)
library(ggplot2)
# Step 1
gpl<-dci_data_ws %>% 
#Step 2
group_by(modality) %>% 
#Step 3
summarise(mean_payments= mean(payment)) %>% 
#Step 4
ggplot(aes(x = modality, y = mean_payments, fill = modality)) +
    geom_bar(stat = "identity") +
    theme_classic() +
    labs(
        x = "Modality",
        y = "Average Payments",
        title = "Average Payments vs Modality"
        ) 

    gpl+ scale_x_discrete(labels=c("HH" = "Home Hemo", "HIC" = "Hemo In-Center",
                              "PD" = "Peritoneal"))

dci_data %>% 
  select(payment,part_a,part_b_phys,part_b_dme,part_b)
#sum(is.na(dci_data$claim_last_dialysis_date))
sum(is.na(dci_data))
[1] 220
str(dci_data)
Classes ‘tbl_df’, ‘tbl’ and 'data.frame':   9970 obs. of  72 variables:
 $ patient_id               : Factor w/ 672 levels "30111","39732",..: 293 50 64 251 21 31 293 86 441 172 ...
 $ dos_year                 : Factor w/ 2 levels "2017","2018": 1 1 2 1 2 2 1 2 2 2 ...
 $ dos_month                : Factor w/ 12 levels "1","2","3","4",..: 7 7 4 7 3 7 9 2 3 8 ...
 $ claim_first_dialysis_date: Date, format: NA NA NA "2017-07-13" ...
 $ claim_last_dialysis_date : Date, format: NA NA NA "2017-07-29" ...
 $ payment                  : num  128637 122674 121244 112103 109108 ...
 $ part_a                   : num  119013 119153 111345 110036 102586 ...
 $ part_b_phys              : num  9623 3521 9899 2067 6521 ...
 $ part_b_dme               : num  0 0 0 0 0 ...
 $ inpatient                : num  119013 119153 111345 108511 102586 ...
 $ outpatient_dialysis      : num  0 0 0 1525 0 ...
 $ outpatient_er            : num  0 0 0 0 0 ...
 $ outpatient_other         : num  0 0 0 0 0 ...
 $ snf                      : num  0 0 0 0 0 ...
 $ vasc_access              : num  179 0 309 0 0 ...
 $ location_id              : Factor w/ 25 levels "000026","000055",..: 18 22 17 24 25 3 18 1 4 5 ...
 $ modality                 : Factor w/ 3 levels "HH","HIC","PD": 2 2 2 2 2 2 2 2 2 2 ...
 $ epo_protocol_flag        : logi  TRUE TRUE TRUE TRUE TRUE TRUE ...
 $ iron_protocol_flag       : logi  FALSE TRUE TRUE TRUE TRUE TRUE ...
 $ nutsup_protocol_flag     : logi  TRUE TRUE TRUE TRUE TRUE TRUE ...
 $ sup_name                 : Factor w/ 11 levels "Body Quest Ice Cream",..: 4 5 9 4 4 11 4 11 11 1 ...
 $ tx                       : Factor w/ 24 levels "0","1","2","3",..: 9 1 5 1 1 3 1 1 6 1 ...
 $ tx_epo                   : Factor w/ 16 levels "0","1","10","11",..: 9 1 2 1 1 8 1 1 2 1 ...
 $ venofer_given            : logi  FALSE FALSE FALSE FALSE FALSE FALSE ...
 $ ferrlecit_given          : logi  TRUE FALSE FALSE FALSE FALSE FALSE ...
 $ feraheme_given           : logi  FALSE FALSE FALSE FALSE FALSE FALSE ...
 $ zemplar_iv_given         : logi  FALSE FALSE FALSE FALSE FALSE FALSE ...
 $ hectorol_iv_given        : logi  TRUE FALSE TRUE FALSE FALSE TRUE ...
 $ calcijex_iv_given        : logi  FALSE FALSE FALSE FALSE FALSE FALSE ...
 $ zemplar_or_given         : logi  FALSE FALSE FALSE FALSE FALSE FALSE ...
 $ hectorol_or_given        : logi  FALSE FALSE FALSE FALSE FALSE FALSE ...
 $ calcijex_or_given        : logi  FALSE FALSE FALSE FALSE FALSE FALSE ...
 $ activase_given           : logi  FALSE FALSE FALSE FALSE FALSE FALSE ...
 $ prostat_given            : logi  TRUE TRUE TRUE TRUE TRUE TRUE ...
 $ nepro_given              : logi  TRUE TRUE TRUE TRUE TRUE TRUE ...
 $ liquacel_given           : logi  TRUE TRUE TRUE TRUE TRUE TRUE ...
 $ hgb                      : num  11.1 0 8.6 0 0 10.4 0 0 0 0 ...
 $ tsat                     : num  23 39 38 23 32 56 0 0 18 50 ...
 $ ferr                     : num  2051 1401 1591 1037 667 ...
 $ albumin                  : num  2.3 0 0 0 0 3.5 0 0 0 0 ...
 $ pth                      : num  559 577 224 0 641 ...
 $ ca                       : num  8.7 0 0 0 0 8.7 0 0 0 0 ...
 $ cca                      : num  8.7 0 0 0 0 9.1 0 0 0 0 ...
 $ ph                       : num  2.3 0 0 0 0 5 0 0 0 0 ...
 $ k                        : num  4.9 0 0 0 0 5.1 0 0 0 0 ...
 $ urr                      : num  72 0 70 0 0 78 0 0 0 0 ...
 $ ktv                      : num  1.45 0 1.35 0 0 1.72 0 0 0 0 ...
 $ has_catheter             : logi  TRUE TRUE TRUE TRUE TRUE TRUE ...
 $ aranesp_given            : logi  TRUE TRUE TRUE TRUE TRUE TRUE ...
 $ protinex_given           : logi  TRUE TRUE TRUE TRUE TRUE TRUE ...
 $ hgb_exclude_flag         : logi  FALSE FALSE FALSE FALSE FALSE FALSE ...
 $ mircera_given            : logi  FALSE FALSE FALSE FALSE FALSE FALSE ...
 $ sensipar_given           : logi  FALSE FALSE TRUE FALSE TRUE TRUE ...
 $ parsabiv_given           : logi  FALSE FALSE TRUE FALSE TRUE TRUE ...
 $ protein_bar_given        : logi  FALSE FALSE FALSE FALSE FALSE TRUE ...
 $ ice_cream_given          : logi  FALSE FALSE FALSE FALSE FALSE TRUE ...
 $ gelatein_given           : logi  FALSE FALSE FALSE FALSE FALSE TRUE ...
 $ active_flag              : logi  TRUE TRUE TRUE TRUE TRUE TRUE ...
 $ hospital_episodes        : num  2 1 2 2 1 3 1 0 1 1 ...
 $ hospital_admits          : num  2 0 2 1 0 3 0 0 1 0 ...
 $ hospital_discharges      : num  1 0 1 1 0 3 0 0 0 0 ...
 $ er_visits                : num  0 0 0 0 0 0 0 0 1 0 ...
 $ snf_episodes             : num  0 0 0 0 0 1 0 1 1 0 ...
 $ snf_admit                : num  0 0 0 0 0 0 0 0 0 0 ...
 $ snf_discharge            : num  0 0 0 0 0 1 0 0 1 0 ...
 $ med_orders               : num  8 16 10 7 12 46 8 9 20 16 ...
 $ cardio                   : num  2 5 2 2 3 8 2 2 1 3 ...
 $ beta_blockers            : num  1 1 0 1 1 1 1 1 1 1 ...
 $ antihypertensives        : num  0 1 0 0 0 3 0 0 0 0 ...
 $ opioids                  : num  1 0 0 0 0 1 1 1 1 0 ...
 $ antidiabetics            : num  0 1 3 1 1 4 0 0 1 3 ...
 $ part_b                   : num  9623 3521 9899 2067 6521 ...

Histograms to understand the distribution of the data for payments

dci_data_ws %>% 
  select (payment,part_a,part_b_phys,part_b_phys) %>% 
  ggplot(aes(x=payment) )+
  geom_histogram(color="#e9ecef", alpha=0.6, position = 'identity', bins=40) +
  scale_x_log10()+
scale_fill_manual(values=c("#69b3a2", "#404080")) +
 labs(x="loggged payment values",
      y="Counts",
      title = "Payment distribution")

#make this interactive
p<- ggplot(dci_data_ws,aes(x=payment,y=..density..)) +
  geom_histogram(bins=40,binwidth = 0.05,fill = "black",color="black",alpha=0.2) +
  scale_x_log10()+
geom_density(color = "red")+
 labs(x="Logged payments",
      y="Frequency",
      title = "Distribution of total payments")
ggplotly(p)

NA
NA
NA
#make this interactive

plt_mod<-dci_data_ws %>% 
          filter(dos_month == 6,dos_year==2017) %>% 
          ggplot(aes(x=payment,fill=modality)) +
          geom_histogram(bins=10,binwidth = 0.25,alpha=0.8,position = "dodge") +
          scale_x_log10()+
          labs(x="loggged payment values",
          y="Frequency",
           title = "Payment distribution")
plt_mod

Modality distributions

#density distribution for modalities
ggplot(dci_data_ws,aes(payment, color = modality,fill=modality)) +
  scale_x_log10()+
  geom_density(alpha = 0.8,position = "dodge") +
  labs(x="Payments",
       y="Density",
       title="Distribution on payments by modality")

dci_data_ws %>% 
  select(payment,modality) %>% 
  group_by(modality) %>% 
  summarise(total_payments=sum(payment),num_of_rows=n())
#Function to create an histgram for each kind of madality HIC,HH AND PD
make_plot <- function(mod){
  dci_data_ws %>% 
  select(payment,modality) %>% 
  filter(modality == mod) %>% 
   ggplot(aes(x=payment)) +
  geom_histogram(binwith=1000) +
  scale_x_log10() +
  labs(x="payments",
       y="frequency",
       title = paste("Distribution of",mod))
}
make_plot('HH')
Ignoring unknown parameters: binwith

make_plot('HIC')
Ignoring unknown parameters: binwith

make_plot('PD')
Ignoring unknown parameters: binwith

dci_data_ws %>% 
  select(payment,modality) %>% 
  filter(modality == 'HH') %>% 
   ggplot(aes(x=payment)) +
  geom_histogram() +
  labs(x="payments",
       y="frequency",
       title = "Distribution of Hemo Home Payments")

NA
dci_data_ws %>% 
select(payment,modality) %>% 
#filter(payment>2800 & payment <3500) %>% 
  group_by(modality) 
NA
NA
NA
NA
dci_data_ws %>% 
  select(payment,modality) %>% 
  filter(payment>2800 & payment <3500) %>% 
  #group_by(modality) %>% 
  filter(modality=='PD') %>% 
  ggplot(aes(x=payment)) +
  geom_histogram(binwidth = 4000)
dci_data_ws %>% 
  select(payment,modality) %>% 
  filter(payment>2800 & payment <3500) 
library(reshape2)
dci_long <- reshape2::melt(dci_data_ws)
ggplot(dci_long, aes(value)) + facet_wrap(~variable, scales = 'free_x') +
  geom_histogram()
  
#frequency distribution with density lines
#x<- sample(0:30, 200, replace=T, prob=15 - abs(15 - 0:30))
x<-dci_data_ws$payment
## Calculate and plot the two histograms
hcum <- h <- hist(x, plot=FALSE)
hcum$counts <- cumsum(hcum$counts)
plot(hcum, main="")
plot(h, add=T, col="grey")

## Plot the density and cumulative density
d <- density(x)
lines(x = d$x, y = d$y * length(x) * diff(h$breaks)[1], lwd = 2)
lines(x = d$x, y = cumsum(d$y)/max(cumsum(d$y)) * length(x), lwd = 2)

#distribution by payment type
 payment_type_dist<-dci_data_ws %>% 
                      select(dos_year,dos_month,payment,part_a,part_b,inpatient,outpatient_dialysis)%>% 
                       pivot_longer(payment:outpatient_dialysis,names_to="payment_type",values_to = "payment") 

saveRDS(payment_type_dist,file="DCI_midcourse/data/payment_type_dist.rds")
#fat tailed dis. 
box_pl<-payment_type_dist %>% 
  filter(dos_year == 2017 & dos_month == 1) %>% 
  ggplot(aes(y = payment,x = payment_type,fill=payment_type)) +
  geom_boxplot()+
  #  scale_y_log10() +
  theme_classic() +
  labs(x="Payment type", y = "Payment",
       title = "Payment distribution by payment types")
 
ggplotly(box_pl)
#plot the fequency distribution across different payment types
  
  pl<-dci_data_ws %>% 
        select(dos_year,dos_month,location_id,payment,inpatient,outpatient_dialysis)%>% 
        pivot_longer(payment:outpatient_dialysis,names_to="payment_type",values_to = "payment") %>% 
        filter(dos_year==2017 & dos_month==1) %>% 
        ggplot( aes(x=payment,fill=payment_type,color= payment_type)) +
        geom_histogram(bins= 40,binwidth = 0.05,alpha=0.5,position = "identity") +
        scale_x_continuous(breaks = seq(0,130000,5000)) +
        scale_x_log10() +
  geom_vline(aes(xintercept = mean(payment,na.rm=T)),color = "red", linetype = "dashed",size = 1) +
  labs(x="Logged payments",y="Frequency",title = "Payments: Inpatient/Hospitalization or Outpatient") 
Scale for 'x' is already present. Adding another scale for 'x', which will replace the existing scale.
        
 pl

sum(is.na(dci_data$payment))

years_plot<- dci_data_ws %>% 
  group_by(dos_year,dos_month) %>% 
  summarise(sum_pay = sum(payment)) %>% 
  ungroup()  

pl <- ggplot( years_plot,aes(y=sum_pay, x = dos_month ,fill=dos_year)) +
  geom_bar(stat = "identity",position = 'dodge') +
  labs(x="Months", y= "Payments") +
  ggtitle("Total payments increase in each month")
       
pl

years_plot
NA
ggplotly(dci_data_ws %>% 
  group_by(modality,dos_month,dos_year) %>% 
  summarise(payments = sum(payment)) %>%  
  ungroup() %>% 
 # ggplot(aes(x=modality,y=payments,fill = `dos_year`)) +
     ggplot(aes(x=dos_month,y=payments,fill = `modality`)) +
  geom_bar(stat="identity",position="dodge" ) )

NA
NA
#show how modalities are doing by total payments 
modality_pl<-dci_data_ws %>% 
  group_by(dos_year,modality) %>% 
  summarise(payments = sum(payment)) %>% 
ungroup() %>% 
  ggplot(aes(x=dos_year,y=payments,fill=modality,color=modality))+
  geom_bar(stat="identity",position="dodge") +
   geom_text(aes(label = round(payments),vjust=0),postion=position_dodge(width=5)) +
labs(x="Modalities in 2017 and 2018",y="payments",title="Payments by modality")
Ignoring unknown parameters: postion
modality_pl

dci_data_ws  %>% 
  ggplot(aes(x=dos_year,y=payment,color = modality)) +
    geom_boxplot() +
  scale_y_log10() +
  labs(x = "Years",y="payments", 
       title = "Payments in in 2017 and 2018")

#Top 50 most expensive patients 
Top50_expensive_patients<-head(arrange(dci_data_ws,desc(payment)), n = 50)

plt_50<-Top50_expensive_patients %>% 
  #mutate(exp_patient = max(payment)) %>% 
  ggplot(aes(y=payment,x=patient_id, fill=modality)) +
  geom_bar(stat = "identity" ) +
  theme_bw()+
  labs(x="Patient ID's",
       y="Payments",
       title="50 expensive patients")

plt_50  + theme(axis.text.x = element_text(angle = 90, hjust = 1))

Percentage bars

library(plotly)
set.seed(123)

df <- dci_data_ws %>% 
  select(payment,inpatient,outpatient_dialysis,modality) %>% 
  pivot_longer(inpatient:outpatient_dialysis,names_to = "hospitalization",values_to = "payments")

p <- ggplot(df, aes(x = modality)) + 
  geom_bar(aes(y = ..count../sum(..count..), fill = hospitalization)) + 
  scale_fill_brewer(palette = "Set3") + 
  ylab("Percent") + 
  ggtitle("Show precentages in bar chart")

p <- ggplotly(p)

p

NA
dci_data_ws %>% 
    select(payment,inpatient,outpatient_dialysis,modality) %>% 
  group_by(modality) %>% 
  summarise(payment=sum(payment), inpatient=sum(inpatient),outpatient=sum(outpatient_dialysis)) %>% 
  ungroup() %>% 
  pivot_longer(inpatient:outpatient,names_to = "payType",values_to = "pays")  %>% 
  ggplot(aes(x=modality,y=payment,fill=payType))+
           geom_bar(stat="identity",position="stack")

other_columns <- c("payment","hospital_episodes","er_visits","cardio","opioids","antidiabetics","beta_blockers","antihypertensives","snf_discharge")
corrs_others <- dci_data_ws %>% select(other_columns) %>% 
  cor()
corrs_others
                       payment hospital_episodes    er_visits       cardio     opioids antidiabetics beta_blockers antihypertensives snf_discharge
payment            1.000000000        0.37753105  0.081022685 -0.002692458  0.10955789   0.068742739   0.012452010      -0.039596398   0.104974700
hospital_episodes  0.377531051        1.00000000  0.138645269  0.033031308  0.10900633   0.045678897   0.037979095      -0.011190044   0.176735065
er_visits          0.081022685        0.13864527  1.000000000  0.013565237  0.05116460   0.003286641   0.018862131      -0.002438958   0.030687705
cardio            -0.002692458        0.03303131  0.013565237  1.000000000 -0.04761030   0.203589325   0.490667836       0.656388881  -0.008774101
opioids            0.109557887        0.10900633  0.051164599 -0.047610303  1.00000000  -0.035631457  -0.064462712      -0.034940410   0.079861605
antidiabetics      0.068742739        0.04567890  0.003286641  0.203589325 -0.03563146   1.000000000   0.089209911       0.022751965   0.032889875
beta_blockers      0.012452010        0.03797909  0.018862131  0.490667836 -0.06446271   0.089209911   1.000000000       0.198152182  -0.004428954
antihypertensives -0.039596398       -0.01119004 -0.002438958  0.656388881 -0.03494041   0.022751965   0.198152182       1.000000000  -0.013584271
snf_discharge      0.104974700        0.17673506  0.030687705 -0.008774101  0.07986161   0.032889875  -0.004428954      -0.013584271   1.000000000
# Change background color to lightblue
corrplot(corrs_others, type = "upper", order = "hclust",
         col = c("black", "white"), bg = "lightblue")

head(dci_data_ws)
#ask michael about how to plot this
dci_data_ws[,6:36] %>% 
  select(-part_a,-part_b_phys,-outpatient_other,-part_b_dme,-inpatient,-outpatient_dialysis,-outpatient_er,-snf,-vasc_access,-epo_protocol_flag,-iron_protocol_flag,-nutsup_protocol_flag,-sup_name,-tx,-tx_epo)
NA

correlational plot

num_columns <- c("hgb","tsat","ferr","albumin","pth","ca","cca","ph","k","urr","ktv")
corrs<-dci_data_ws %>% select(num_columns) %>% 
 # drop_na_() %>% 
  cor()
corrs
               hgb          tsat        ferr    albumin          pth         ca        cca            ph         k        urr         ktv
hgb     1.00000000  0.0527380941  0.02570081 0.59609612  0.045803409 0.58340275 0.56441343  0.3008968876 0.4724638 0.21430294 0.247192331
tsat    0.05273809  1.0000000000  0.39986167 0.08697933 -0.027163707 0.04433107 0.03910477  0.0002758743 0.0788412 0.06797837 0.087991355
ferr    0.02570081  0.3998616659  1.00000000 0.05098390  0.005239110 0.05485813 0.05667298 -0.0514526023 0.1183593 0.20079170 0.064636183
albumin 0.59609612  0.0869793324  0.05098390 1.00000000  0.104339811 0.76287074 0.67532722  0.3997004606 0.6248656 0.31227746 0.270849884
pth     0.04580341 -0.0271637069  0.00523911 0.10433981  1.000000000 0.03478453 0.01573087  0.2972633464 0.1093904 0.02051048 0.004094452
ca      0.58340275  0.0443310656  0.05485813 0.76287074  0.034784525 1.00000000 0.98442825  0.3359632961 0.6256086 0.27040412 0.303778243
cca     0.56441343  0.0391047722  0.05667298 0.67532722  0.015730870 0.98442825 1.00000000  0.3196373678 0.6140480 0.25157942 0.306643666
ph      0.30089689  0.0002758743 -0.05145260 0.39970046  0.297263346 0.33596330 0.31963737  1.0000000000 0.4445911 0.08190045 0.076739150
k       0.47246376  0.0788412002  0.11835935 0.62486563  0.109390410 0.62560864 0.61404796  0.4445910518 1.0000000 0.34881524 0.209681668
urr     0.21430294  0.0679783689  0.20079170 0.31227746  0.020510483 0.27040412 0.25157942  0.0819004513 0.3488152 1.00000000 0.080500799
ktv     0.24719233  0.0879913547  0.06463618 0.27084988  0.004094452 0.30377824 0.30664367  0.0767391501 0.2096817 0.08050080 1.000000000
num_columns <- c("payment","hgb","tsat","ferr","albumin","pth","ca","cca","ph","k","urr","ktv")
corrs<-dci_data_ws %>% select(num_columns)  %>% 
cor()


corrplot(corrs,type = "upper",order = "hclust",
         tl.col="black",tl.srt=45)

NA
NA
tibble('variable' = corrs[1,2:12] %>% names(),'correlation' = corrs[1,2:12]) %>% 
  ggplot(aes(x=reorder(variable,correlation),y = correlation)) +
  geom_point()+
  geom_segment(aes(xend=variable,yend=0))+
  coord_flip() +
  geom_hline(yintercept = 0) +
  labs(x ="Labs",
       y ="Correlation",
       title = "Correlation between Lab values and Payments")

pl <- ggplot(dci_data_ws, aes(x=albumin,y=payment) ) +
  geom_point(alpha=0.2) + geom_smooth(method = 'lm') +
  scale_x_log10() +
  scale_y_log10()

ggplotly(pl)
Transformation introduced infinite values in continuous x-axisTransformation introduced infinite values in continuous x-axisRemoved 195 rows containing non-finite values (stat_smooth).
#unique(dci_data_ws$ktv)
#hgb vs payment

ggplot(dci_data_ws, aes(x=hgb,y=payment) ) +
  geom_point() + geom_smooth(method = 'lm') +
  scale_x_log10() +
  labs(x="hgb", y = "payment", title = "Payment Vs hgb")

ggplot(dci_data_ws, aes(x=ca,y=payment) ) +
  geom_point() + geom_smooth(method = 'lm') +
  scale_x_log10() +
  labs(x="ca", y = "payment", title = "Payment Vs ca")

Maps

#first prep the dataset to get the information on the map markers

 payment_summary_by_loc<-dci_data_ws %>% 
  select(patient_id,location_id,dos_month,dos_year,payment,part_a,part_b_phys,part_b_dme,modality) %>% 
  group_by(location_id,dos_month,dos_year ) %>% 
  summarise(
            total_patients = NROW(patient_id),
            totalpayments = round(sum(payment),digits=2),
            min_pay = min(payment),
            max_pay = max(payment),
            avg_pay = sum(payment)/NROW(patient_id)) %>% 
  ungroup() %>%
  arrange(dos_year,dos_month)  

#merge the grouped data with location dataset
payment_geom_summary <- merge(payment_summary_by_loc,locations,by = "location_id")

payment_geom_summary %>%
  filter(location_id =='000055' & dos_month ==1 & dos_year ==2017)
  
#save it to rds file
saveRDS(payment_geom_summary, file = "DCI_midcourse/data/payment_geom_summary.rds")

 
payment_geom_summary %>% 
  arrange(desc(totalpayments)) %>% 
  filter(dos_year==2017 & dos_month == 1)
NA
#Top 5 locations with high average payments

loc_plt<-payment_summary_by_loc %>% 
  arrange(desc(totalpayments)) %>% 
  filter(dos_year==2017 & dos_month == 4) %>% 
  top_n(5) %>% 
  ggplot(aes(x=location_id,y=avg_pay)) +
  geom_col( )
Selecting by avg_pay
ggplotly(loc_plt)

NA
NA
leaflet(data= locations) %>% 
  addTiles() %>% 
  addMarkers(~longitude,
             ~latitude,
             popup = ("hello"))
pl <- ggplot(dci_data_ws, aes(x=albumin,y=payment) ) +
  geom_point(alpha=0.2) + geom_smooth(method = 'lm') +
  scale_x_log10() +
  scale_y_log10()

ggplotly(pl)
dci_data_ws %>% 
  select(dos_year,dos_month,payment,part_a,part_b) %>% 
    filter(dos_year==2017,dos_month==1) %>% 
  pivot_longer(part_a:part_b,names_to = "payType",values_to = "payments") %>% 
  ggplot(aes(x=payType,y=payments,fill=payments))+
           geom_bar(stat="identity",position="dodge")+
  labs(x="Payment Types",
       y="Payments",
       title = "Payments  by Payment types")

NA
NA
NA
NA
NA
#Payments by Modalities

show_plot<-dci_data_ws %>% 
               select(dos_year,dos_month,payment,part_a,part_b,modality) %>% 
              filter(dos_year==2018,dos_month==1) %>% 
              ggplot(aes(x=modality,y=payment,fill=payment))+
              geom_bar(stat="identity",position="dodge",alpha=0.3)+
              labs(x="Modalities",
              y="Payments",
              title = "Payments  by Modalities")
show_plot + scale_x_discrete(labels=c("HH" = "Home Hemo", "HIC" = "Hemo In-Center",
                              "PD" = "Peritoneal"))

dci_data_ws %>% 
  select(dos_year,dos_month,payment,part_a,part_b) %>% 
  mutate(percent_part_a = round(part_a/payment*100)) %>% 
  filter(dos_year==2017,dos_month==1)
NA
dci_data_shiny %>% 
  select (location_id,patient_id,payment,part_a,part_b,modality)
NA
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKVGhpcyBpcyBhbiBbUiBNYXJrZG93bl0oaHR0cDovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbSkgTm90ZWJvb2suIFdoZW4geW91IGV4ZWN1dGUgY29kZSB3aXRoaW4gdGhlIG5vdGVib29rLCB0aGUgcmVzdWx0cyBhcHBlYXIgYmVuZWF0aCB0aGUgY29kZS4gCgpUcnkgZXhlY3V0aW5nIHRoaXMgY2h1bmsgYnkgY2xpY2tpbmcgdGhlICpSdW4qIGJ1dHRvbiB3aXRoaW4gdGhlIGNodW5rIG9yIGJ5IHBsYWNpbmcgeW91ciBjdXJzb3IgaW5zaWRlIGl0IGFuZCBwcmVzc2luZyAqQ21kK1NoaWZ0K0VudGVyKi4gCmBgYHtyfQpvcHRpb25zKHNjaXBlbiA9IDk5OSkKYGBgCgpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShwbG90bHkpCmxpYnJhcnkoZGF0YS50YWJsZSkKbGlicmFyeShsdWJyaWRhdGUpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoY29ycnBsb3QpCmxpYnJhcnkobGVhZmxldCkKYGBgCgpgYGB7cn0KI0dldCBvbmx5IHRoZSBTdW1tYXJ5IGRhdGEgZm9yIHNvbWUgaW5pdGlhbCBhbmFseXNpcwoKc3VtbWFyeV9yYXdfZGF0YTwtcmVhZF9jc3YgKCdkYXRhL2NsYWltX3N1bW1hcnlfdjEuY3N2JyApCnN1bW1hcnlfd2RzPC1zdW1tYXJ5X3Jhd19kYXRhCmBgYApgYGB7cn0KI0dldCB0aGUgZGF0YSB3aXRoIGFsbCB0aGUgcmVxdWlyZWQgZmllbGRzIGZvciBhbmFseXNpcwojY2xhaW1fZGV0YWlsX3Jhd19kYXRhPC1mcmVhZCgiZGF0YS9jbGFpbV9kZXRhaWxzLmNzdiIsc2VwID0gInwiLGZpbGwgPSBUKQoKI2RldGFpbF9yYXdfZGF0YTwtcmVhZF9jc3YgKCdkYXRhL2NsYWltX2RldGFpbHMuY3N2JyApCmBgYApgYGB7cn0KbG9jYXRpb25zPC1yZWFkX2NzdignZGF0YS9FU0NvX0xPQ0FUSU9OU19sby5jc3YnICkKYGBgCklOSVRJQUwgQU5BTFlTSVMgV0lUSCBUSEUgU1VNTUFSWSBEQVRBIE9OTFkuCiAKYGBge3J9CgpzdW1tYXJ5X3dkcyAlPiUgCiAgc2VsZWN0ICgtZXNjb19pZCwtYmVuZV9oaWNfbnVtLC1lc2NvX2FsaWduZWRfZmxhZykgJT4lIAogIGZpbHRlcihwYXRpZW50X2lkID09ICc4MTE0NTQnKSAlPiUgCiAgYXJyYW5nZShkb3NfeWVhcixkb3NfbW9udGgpCgpgYGAKCmBgYHtyfQpzdHIoc3VtbWFyeV93ZHMpCmBgYApgYGB7cn0Kc3VtbWFyeShzdW1tYXJ5X3dkcykKYGBgCmBgYHtyfQpzdW1tYXJ5KHN1bW1hcnlfd2RzJHBheW1lbnQpCmBgYAoKYGBge3J9CnN1bW1hcnlfd2RzICU+JSAKICBnZ3Bsb3QoYWVzKHg9cGF5bWVudCkpICsKICBnZW9tX2hpc3RvZ3JhbShicmVha3MgPSBzZXEoNTAwLDEwMDAwMCxieT0xMDAwKSwKICAgICAgICAgICAgICAgICBiaW5zPTIwLAogICAgICAgICAgICAgICAgIGNvbD0icmVkIiwKICAgICAgICAgICAgICAgICBmaWxsID0gImdyZWVuIiwKICAgICAgICAgICAgICAgICBhbHBoYSA9IDAuMikgKwogc2NhbGVfeF9sb2cxMCgpICArCiAgbGFicyh4PSJQYXltZW50cyIsIHkgPSAiQ291bnRzIix0aXRsZSA9ICJQYXltZW50cyBIaXN0b2dyYW0iKSAgCmBgYAogCiAKCmNoYW5nZV9pbmNyZWFzZTwtc3VtbWFyeV93ZHMgJT4lIAogIHNlbGVjdCAocGF0aWVudF9pZCxwYXltZW50LGRvc195ZWFyLGRvc19tb250aCkgJT4lIAogIGdyb3VwX2J5KHBhdGllbnRfaWQsZG9zX3llYXIsYWRkPVRSVUUpICU+JSAKICBzdW1tYXJpc2Uoc3VtX3BheW1lbnQgPSBzdW0ocGF5bWVudCksIG51bV9vZl9tb250aHMgPSBOUk9XKGRvc19tb250aCkpICU+JSAKICB1bmdyb3VwICU+JSAKICBmaWx0ZXIobnVtX29mX21vbnRocyA+MTEpICU+JSAKICBhcnJhbmdlIChudW1fb2ZfbW9udGhzLHBhdGllbnRfaWQsZG9zX3llYXIsZGVzYyhzdW1fcGF5bWVudCkpIAoKCmNoYW5nZV9pbmNyZWFzZSRwYXRpZW50X2lkIDwtIGFzLmZhY3RvcihjaGFuZ2VfaW5jcmVhc2UkcGF0aWVudF9pZCkKCiBjaGFuZ2VfaW5jcmVhc2UgJT4lIAogIGZpbHRlciAocGF0aWVudF9pZCA9PSAnNDAzNjc1JykKCmNoYW5nZV9pbmNyZWFzZSRwYXRpZW50X2lkIDwtIGFzLmZhY3RvcihjaGFuZ2VfaW5jcmVhc2UkcGF0aWVudF9pZCApCmNoYW5nZV9pbmNyZWFzZSRkb3NfeWVhciA8LSBhcy5mYWN0b3IoY2hhbmdlX2luY3JlYXNlJGRvc195ZWFyKQoKcGwgPC0gZ2dwbG90KCBjaGFuZ2VfaW5jcmVhc2UsYWVzKHk9c3VtX3BheW1lbnQsIHggPSBwYXRpZW50X2lkICxmaWxsPWRvc195ZWFyKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLHBvc2l0aW9uID0gJ2RvZGdlJykgKwogIGxhYnMoeD0icGF0aWVudF9pZCIsIHk9ICJQYXltZW50cyIpICsKICBnZ3RpdGxlKCJ5ZWFybHkgcGF5bWVudHMgZGlmZmVyZW5jZSBmb3IgcGF0aWVudHMiKQogICAgICAgCnBsCgoKI3Bpdm90IHRoZSBkYXRhIGFuZCB1bmRlcnN0YW5kIGh0ZSBwZXJjZW50YWdlIGNoYW5nZSBpbiBwYXltZW50cyBhbmQgZ2V0IGV4cGVuc2l2ZSBwYXRpZW50cwpleHBlbnNpdmVfcGF0aWVudHM8LXBpdm90X3dpZGVyKGNoYW5nZV9pbmNyZWFzZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lc19mcm9tID0gZG9zX3llYXIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVzX2Zyb20gPSBzdW1fcGF5bWVudCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVzX2ZpbGwgPSBsaXN0KHN1bV9wYXltZW50ID0gMCkpICU+JSAKICAgICAgICAgIG11dGF0ZShwZXJjZW50X2NoYW5nZSA9IChgMjAxOGAtYDIwMTdgKS9gMjAxN2AgKiAxMDApICU+JSAKICAgICAgICAgIGZpbHRlcihwZXJjZW50X2NoYW5nZSA+IDUwICYgYDIwMTdgICE9IDApICU+JSAKICAgICAgICAgIGFycmFuZ2UgKGRlc2MocGVyY2VudF9jaGFuZ2UpKQoKZXhwZW5zaXZlX3BhdGllbnRzCgoKCmBgYHtyfQpzdW1tYXJ5X3dkcyAlPiUgCiAgZmlsdGVyKHBhdGllbnRfaWQgPT0nNzk4MDk0JykgJT4lIAogIGFycmFuZ2UgKGRvc195ZWFyLGRvc19tb250aCkKCmBgYAoKCmBgYHtyfQpsaWJyYXJ5KGRwbHlyKQp5ZWFyX3Bsb3Q8LSBzdW1tYXJ5X3dkcyAlPiUgCiAgZ3JvdXBfYnkoZG9zX3llYXIsZG9zX21vbnRoKSAlPiUgCiAgc3VtbWFyaXNlKHN1bV9wYXkgPSBzdW0ocGF5bWVudCkpICU+JSAKICB1bmdyb3VwKCkgIAp5ZWFyX3Bsb3QKCnllYXJfcGxvdCRkb3NfbW9udGggPC0gYXMuZmFjdG9yKHllYXJfcGxvdCRkb3NfbW9udGgpCnllYXJfcGxvdCRkb3NfeWVhciA8LSBhcy5mYWN0b3IoeWVhcl9wbG90JGRvc195ZWFyKQoKcGwgPC0gZ2dwbG90KCB5ZWFyX3Bsb3QsYWVzKHk9c3VtX3BheSwgeCA9IGRvc19tb250aCAsZmlsbD1kb3NfeWVhcikpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5Iixwb3NpdGlvbiA9ICdkb2RnZScpICsKICBsYWJzKHg9Ik1vbnRocyIsIHk9ICJQYXltZW50cyIpICsKICBnZ3RpdGxlKCJJbmNyZWFzZSBpbiBQYXltZW50cyBmcm9tIDIwMTcgdG8gMjAxOCIpCgoKcGwKICAKYGBgCgoKYGBge3J9CiNyZWRvIHRoaXMgd2l0aCBub24gc3VtbWFyaXplIHJhdyBkYXRhCgpwbGJveCA8LSBnZ3Bsb3QoeWVhcl9wbG90LGFlcyh5PXN1bV9wYXksIHggPSBkb3NfbW9udGgsZmlsbD1kb3NfbW9udGgpICkrCiAgICAgICAgIGdlb21fYm94cGxvdCgpICsKICAgICAgICAgbGFicyh4PSJNb250aHMiLCB5PSAiUGF5bWVudHMiKSArCiAgICAgICAgZ2d0aXRsZSgiRGlzdHJpYnV0aW9uIG9mIFBheW1lbnRzIGJ5IE1vbnRocyIpICsKICAgICAgICAgdGhlbWVfZGFyaygpCiAgICAgICAKcGxib3gKIApgYGAKYGBge3J9CgojcmVkbyB0aGlzIHdpdGggbm9uIHN1bW1hcml6ZSByYXcgZGF0YQoKIGRjaV9kYXRhX3dzICU+JSAKICAgICAgICAgc2VsZWN0KHBhdGllbnRfaWQsbW9kYWxpdHkscGF5bWVudCkgJT4lIAogICAgICAgICBmaWx0ZXIobW9kYWxpdHkgPT0nSElDJykgJT4lICAgICAgCiAgICAgICAgIGFycmFuZ2UoZGVzYyhwYXltZW50KSkgICU+JSAKICAgICAgICAgaGVhZChuID0gMzApICU+JSAKICAgICAgICAgZ2dwbG90KGFlcyh4PXJlb3JkZXIocGF0aWVudF9pZCxwYXltZW50KSx5PXBheW1lbnQsZmlsbD1wYXRpZW50X2lkKSkrCiAgICAgICAgIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikgKwogICAgICAgICBjb29yZF9mbGlwKCkgKwogICAgICAgICBsYWJzKHg9IlBhdGllbnQgSUQiLAogICAgICAgICAgICAgIHk9IlBheW1lbnRzIiwKICAgICAgICAgICAgICB0aXRsZSA9ICJUb3AgMzAgcGF0aWVudHMgd2l0aCBoaWdoIHBheW1lbnRzIikKICAKICAgICAgIAogICAgICAgIAoKCgoKYGBgCgoKQWRkIGEgbmV3IGNodW5rIGJ5IGNsaWNraW5nIHRoZSAqSW5zZXJ0IENodW5rKiBidXR0b24gb24gdGhlIHRvb2xiYXIgb3IgYnkgcHJlc3NpbmcgKkNtZCtPcHRpb24rSSouCgpXaGVuIHlvdSBzYXZlIHRoZSBub3RlYm9vaywgYW4gSFRNTCBmaWxlIGNvbnRhaW5pbmcgdGhlIGNvZGUgYW5kIG91dHB1dCB3aWxsIGJlIHNhdmVkIGFsb25nc2lkZSBpdCAoY2xpY2sgdGhlICpQcmV2aWV3KiBidXR0b24gb3IgcHJlc3MgKkNtZCtTaGlmdCtLKiB0byBwcmV2aWV3IHRoZSBIVE1MIGZpbGUpLiAKClRoZSBwcmV2aWV3IHNob3dzIHlvdSBhIHJlbmRlcmVkIEhUTUwgY29weSBvZiB0aGUgY29udGVudHMgb2YgdGhlIGVkaXRvci4gQ29uc2VxdWVudGx5LCB1bmxpa2UgKktuaXQqLCAqUHJldmlldyogZG9lcyBub3QgcnVuIGFueSBSIGNvZGUgY2h1bmtzLiBJbnN0ZWFkLCB0aGUgb3V0cHV0IG9mIHRoZSBjaHVuayB3aGVuIGl0IHdhcyBsYXN0IHJ1biBpbiB0aGUgZWRpdG9yIGlzIGRpc3BsYXllZC4KCgoKYGBge3J9CnN1bW1hcnlfMjAxNzwtc3VtbWFyeV93ZHMgJT4lIAogIGdyb3VwX2J5KGRvc19tb250aCxkb3NfeWVhcikgJT4lIAogIHN1bW1hcmlzZSgKICAgICAgICAgICAgdG90YWxfcGF0aWVudHMgPSBOUk9XKHBhdGllbnRfaWQpLAogICAgICAgICAgICB0b3RhbHBheW1lbnRzID0gc3VtKHBheW1lbnQpLAogICAgICAgICAgICBtaW5fcGF5ID0gbWluKHBheW1lbnQpLAogICAgICAgICAgICBtYXhfcGF5ID0gbWF4KHBheW1lbnQpLAogICAgICAgICAgICBhdmdfcGF5ID0gc3VtKHBheW1lbnQpL05ST1cocGF0aWVudF9pZCkpICU+JSAKICB1bmdyb3VwKCkgJT4lCiAgYXJyYW5nZShkb3NfeWVhcixkb3NfbW9udGgpICU+JSAKICBmaWx0ZXIoZG9zX3llYXIgPT0iMjAxNyIpCgpzdW1tYXJ5XzIwMTcKYGBgCgpgYGB7cn0Kc3VtbWFyeV8yMDE3X3Bpdm90IDwtIHN1bW1hcnlfMjAxNyAlPiUgCiAgICAgICAgICAgICAgICAgICAgICBwaXZvdF9sb25nZXIobWluX3BheTphdmdfcGF5LCBuYW1lc190byA9ICJwYXltZW50X3R5cGUiLCB2YWx1ZXNfdG8gPSAicGF5bWVudCIpCgpzdW1tYXJ5XzIwMTdfcGl2b3QkZG9zX21vbnRoID0gYXMuZmFjdG9yKHN1bW1hcnlfMjAxN19waXZvdCRkb3NfbW9udGgpCgpzdW1tYXJ5XzIwMTdfcGl2b3QKCmBgYAoKYGBge3J9CiAKcGw8LSBnZ3Bsb3Qoc3VtbWFyeV8yMDE3X3Bpdm90LGFlcyh4PWRvc19tb250aCwgeSA9IHBheW1lbnQsIGZpbGwgPSBwYXltZW50X3R5cGUpKSArCiAgICAgIGdlb21fY29sKHN0YXQgPSAiaWRlbnRpdHkiLHBvc2l0aW9uID0gJ2RvZGdlJykgKwogICAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSA2MDAwLCBsaW5ldHlwZSA9ICJkYXNoZWQiLGNvbG9yID0gImRhcmtyZWQiKSArCiAgICAgIGxhYnMoeD0iTW9udGhzIiwgeSA9ICJQYXltZW50cyIpICsKICAgICAgZ2d0aXRsZSgiMjAxNyBtaW5pbXVtLCBtYXhpbXVtIGFuZCBhdmVyYWdlIHBheW1lbnRzIikKCnBsICsgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLDEzMDAwMCw1MDAwKSkKIAogIApgYGAKYGBge3J9CmFsbF9wYXltZW50czwtc3VtbWFyeV93ZHMgJT4lIAogIGdyb3VwX2J5KGRvc19tb250aCkgJT4lIAogIHN1bW1hcmlzZSgKICAgICAgICAgICAgdG90YWxfcGF0aWVudHMgPSBOUk9XKHBhdGllbnRfaWQpLAogICAgICAgICAgICB0b3RhbHBheW1lbnRzID0gc3VtKHBheW1lbnQpLAogICAgICAgICAgICBtaW5fcGF5ID0gbWluKHBheW1lbnQpLAogICAgICAgICAgICBtYXhfcGF5ID0gbWF4KHBheW1lbnQpLAogICAgICAgICAgICBhdmdfcGF5ID0gc3VtKHBheW1lbnQpL05ST1cocGF0aWVudF9pZCkpICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIHBpdm90X2xvbmdlcihtaW5fcGF5OmF2Z19wYXksIG5hbWVzX3RvPSdwYXltZW50X3R5cGUnLHZhbHVlc190byA9ICdwYXltZW50cycpCgphbGxfcGF5bWVudHMKYGBgCgpgYGB7cn0KI3JlZG8gIHdpdGggYm94IHBsb3QKCnBsX2FsbDwtIGdncGxvdChhbGxfcGF5bWVudHMsYWVzKHg9ZG9zX21vbnRoLCB5ID0gcGF5bWVudHMsIGZpbGwgPSBwYXltZW50X3R5cGUpKSArCiAgICAgIGdlb21fY29sKHN0YXQgPSAiaWRlbnRpdHkiLHBvc2l0aW9uID0gJ2RvZGdlJykgKwogICAgICBzY2FsZV94X2NvbnRpbnVvdXMobmFtZSA9Ik1vbnRocyIsYnJlYWtzID0gc2VxKDEsMTIsMSkpICsKICAgICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gNjAwMCwgbGluZXR5cGUgPSAiZGFzaGVkIixjb2xvciA9ICJkYXJrcmVkIikgKwogICAgICBsYWJzKHg9Ik1vbnRocyIsIHkgPSAiUGF5bWVudHMiKSArCiAgICAgIGdndGl0bGUoIk1pbmltdW0sIE1heGltdW0gYW5kIEF2ZXJhZ2UgcGF5bWVudHMiKQoKCiAgCnBsX2FsbCArIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCwxMzAwMDAsNTAwMCkpCgpgYGAKCkFOQUxZU0lTIFVTSU5HIFNVTU1BUlkgQU5EIERFVEFJTCBEQVRBCkdldCB0aGUgZGF0YSBhbmQgY2xlYW4gaXQgCmBgYHtyfQojZ2V0IGRldGFpbCBhbmQgc3VtbWFyeSBkYXRhIGFuZCBzYXZlIGl0IGluIGEgZGYKZGV0YWlsX3Jhd19kYXRhPC1yZWFkX2NzdiAoJ2RhdGEvY2xhaW1fZGV0YWlscy5jc3YnICkKCmRjaV9kYXRhPC1kZXRhaWxfcmF3X2RhdGEKCmRjaV9kYXRhPC1kY2lfZGF0YSAlPiUKc2VsZWN0KC1lc2NvX2lkLC1iZW5lX2hpY19udW0sLWZ1bGxfZW5jb3VudGVyLC1waHlzX25lcGgsLXBoeXNfaG9zcCwtcGh5c19lZCwtYW1idWxhbmNlLC1waHlzX290aGVyLC1lc2NvX2FsaWduZWRfZmxhZywtaW5wYXRpZW50X2ZsdWlkLC1vdXRwYXRpZW50X2VyX2ZsdWlkLC1wYXJ0X2Ffb3RoZXJfZmx1aWQsLXBhdGllbnRfaWRfMSwtZG9zX3l5eXksLWRvc19tbSwtZXNyZF9kYXRlLC1oZ2JfZGF0ZSwtdHNhdF9kYXRlLC1mZXJyX2RhdGUsLWFsYnVtaW5fZGF0ZSwtcHRoX2RhdGUsLWNhX2RhdGUsLWNjYV9kYXRlLC1waF9kYXRlLC1rX2RhdGUsLXVycl9kYXRlLC1rdHZfZGF0ZSwtZXBvX2dpdmVuLC12ZW5vZmVyX3dhc3RlZCwtaW5wYXRpZW50X2FjY2Vzcywtb3V0cGF0aWVudF9lcl9hY2Nlc3MsLXBhcnRfYV9vdGhlcl9hY2Nlc3MsLWRjaV9jbGFpbXMsLW5vbl9kY2lfY2xhaW1zLC1oaGEsLWhvc3BpY2UsLWRtZSwtc3RhcnRfZGF0ZSwtZW5kX2RhdGUsLWVwb19jZWlsaW5nLC1yb3V0ZV9mcmVxLC1kcnVnX25hbWUsLWZlcnJpdGluX2N1dG9mZiwtdHNhdF9jdXRvZmYsLWhnYl9jdXRvZmYsLWZlcnJsZWNpdF93YXN0ZWQsLXplbXBsYXJfaXZfd2FzdGVkLC1jYWxjaWpleF9pdl93YXN0ZWQsLWZlcmFoZW1lX3dhc3RlZCwtaGVjdG9yb2xfaXZfd2FzdGVkLC10eF9taXNzZWQsLXNlbnNpcGFyX2Rpc3BlbnNlZCkKCiNtYWtlIHN1cmUgYWxsIHRoZSBjb2x1bW5zIGFyZSBpbiBjb3JyZWN0IGRhdGEgdHlwZXMuCgojY2hhbmdlIGNsYWltcyBkYXRlIGNvbHVtbnMgdG8gZGF0ZSBkYXRhdHlwZQpkYXRlX2NvbHVtbnMgPC0gYygiY2xhaW1fZmlyc3RfZGlhbHlzaXNfZGF0ZSIsImNsYWltX2xhc3RfZGlhbHlzaXNfZGF0ZSIpCmRjaV9kYXRhW2RhdGVfY29sdW1uc10gPC0gbGFwcGx5KGRjaV9kYXRhW2RhdGVfY29sdW1uc10sYXMuRGF0ZSkKCiNjaGFuZ2UgdGhlIG90aGVyIGNvbHVtbnMgdG8gZmFjdG9yCmZhY19jb2x1bW5zIDwtIGMoInBhdGllbnRfaWQiLCJkb3NfeWVhciIsImxvY2F0aW9uX2lkIiwiZG9zX21vbnRoIiwibW9kYWxpdHkiLCJ0eCIsInR4X2VwbyIsInN1cF9uYW1lIikKZGNpX2RhdGFbZmFjX2NvbHVtbnNdIDwtIGxhcHBseShkY2lfZGF0YVtmYWNfY29sdW1uc10sYXMuZmFjdG9yKQoKI2NoYW5nZSB0aGUgYmVsb3cgY29sdW1ucyB0byBsb2dpY2FsCmJvb2xfY29sdW1ucyA8LSBjKCJlcG9fcHJvdG9jb2xfZmxhZyIsImlyb25fcHJvdG9jb2xfZmxhZyIsIm51dHN1cF9wcm90b2NvbF9mbGFnIiwiaGdiX2V4Y2x1ZGVfZmxhZyIsImFjdGl2ZV9mbGFnIikKZGNpX2RhdGFbYm9vbF9jb2x1bW5zXSA8LSBsYXBwbHkoZGNpX2RhdGFbYm9vbF9jb2x1bW5zXSxhcy5sb2dpY2FsKQogCiNNYWtlIGJlbG93IGNvbHVtcyBhcyBsb2dpY2FsIHRydWUgaWYgdGhleSBoYXZlIGFueSB2YWx1ZSBlbHNlIGlmIHRoZXkgaGF2ZSBudWxsIG1ha2UgaXQgbG9naWNhbCBmYWxzZS4KZGNpX2RhdGE8LWRjaV9kYXRhICU+JSAKICBtdXRhdGVfYXQodmFycygiZmVycmxlY2l0X2dpdmVuIiwiZmVyYWhlbWVfZ2l2ZW4iLCJ2ZW5vZmVyX2dpdmVuIiwiemVtcGxhcl9pdl9naXZlbiIsImhlY3Rvcm9sX2l2X2dpdmVuIiwiY2FsY2lqZXhfaXZfZ2l2ZW4iLCJ6ZW1wbGFyX29yX2dpdmVuIiwiaGVjdG9yb2xfb3JfZ2l2ZW4iLCJjYWxjaWpleF9pdl9naXZlbiIsInplbXBsYXJfb3JfZ2l2ZW4iLCJoZWN0b3JvbF9vcl9naXZlbiIsImNhbGNpamV4X29yX2dpdmVuIiwiYWN0aXZhc2VfZ2l2ZW4iLCJwcm9zdGF0X2dpdmVuIiwibmVwcm9fZ2l2ZW4iLCJsaXF1YWNlbF9naXZlbiIsImhhc19jYXRoZXRlciIsImFyYW5lc3BfZ2l2ZW4iLCJwcm90aW5leF9naXZlbiIsIm1pcmNlcmFfZ2l2ZW4iLCJzZW5zaXBhcl9naXZlbiIsInBhcnNhYml2X2dpdmVuIiwicHJvdGVpbl9iYXJfZ2l2ZW4iLAogICAgICAgICAgICAgICAgICJpY2VfY3JlYW1fZ2l2ZW4iLCJnZWxhdGVpbl9naXZlbiIpLAogICAgICAgICAgICBmdW5zKGNhc2Vfd2hlbiguPT0iTlVMTCIgfiBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+IFRSVUUpKSkKCiNGSVJTVCBtYWtlIHRoZSBudWxsIFZBTFVFUyBpbiBjaGFyIGNvbCB0byB6ZXJvJ3MgZXhjZXB0IGZvciBkYXRlIGNvbHVtbnMKCm51bV9jb2x1bW5zIDwtIGMoImhnYiIsInRzYXQiLCJmZXJyIiwiYWxidW1pbiIsInB0aCIsImNhIiwiY2NhIiwicGgiLCJrIiwidXJyIiwia3R2IiwidHhfZXBvIikKZGNpX2RhdGFbbnVtX2NvbHVtbnNdPC1kY2lfZGF0YVtudW1fY29sdW1uc10lPiUgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXBsYWNlKC49PSJOVUxMIiwiMCIpIAoKI2NoYW5nZSBhbGwgdGhlIGNoYXJhY3RlciBjb2x1bW5zIG90IG51bWVyaWMKZGNpX2RhdGE8LWRjaV9kYXRhICU+JSBtdXRhdGVfaWYoaXMuY2hhcmFjdGVyLGFzLm51bWVyaWMpCiAKI25hbWVzKGRjaV9kYXRhKQogCiNhcyBmb3IgZGF0ZSBjb2x1bW5zIHdlIGNhbm5vdCByZXBsYWNlIG5hIHZhbHVlcyBvdCAwLiBmaXJzdCBtYWtlIHRoZW0gY2hhcmFjdGVyIGNvbHVtbnMgYW5kIHRoZW4gbWFrZSByZXN0IHRvIHRoZSBuYSB2YWx1ZXMgdG8gMCBpbiBlbnRpcmUgZGF0YWZyYW1lCmRjaV9kYXRhJGNsYWltX2ZpcnN0X2RpYWx5c2lzX2RhdGUgPC1hcy5jaGFyYWN0ZXIuRGF0ZShkY2lfZGF0YSRjbGFpbV9maXJzdF9kaWFseXNpc19kYXRlICkKZGNpX2RhdGEkY2xhaW1fbGFzdF9kaWFseXNpc19kYXRlIDwtYXMuY2hhcmFjdGVyLkRhdGUoZGNpX2RhdGEkY2xhaW1fbGFzdF9kaWFseXNpc19kYXRlICkKIAojbWFrZSBhbGwgbmEgdmFsdWVzIHRvIDAgaW4gZW50aXJlIGRhdGFmcmFtZQogZGNpX2RhdGFbaXMubmEoZGNpX2RhdGEpXTwtMAojIHN1bShpcy5uYShkY2lfZGF0YSkpCgogI21ha2luZyB0aGUgZGF0ZXMgY29sdW1uIGJhY2sgdG8gZGF0ZSBkYXRhdHlwZQpkY2lfZGF0YSRjbGFpbV9maXJzdF9kaWFseXNpc19kYXRlIDwtIGFzLkRhdGUoZGNpX2RhdGEkY2xhaW1fZmlyc3RfZGlhbHlzaXNfZGF0ZSkKZGNpX2RhdGEkY2xhaW1fbGFzdF9kaWFseXNpc19kYXRlIDwtIGFzLkRhdGUoZGNpX2RhdGEkY2xhaW1fbGFzdF9kaWFseXNpc19kYXRlKQoKI2RlbGV0ZSB0aGUgb3V0bGllcnMoIHBheW1lbnRzIHdoaWNoIGFyZSBsZXNzIHRoYW4gMTUwMCkKZGNpX2RhdGE8LWRjaV9kYXRhICU+JSAKICBmaWx0ZXIoYHBheW1lbnRgPjE1MDApICU+JSAKICBhcnJhbmdlKGRlc2MocGF5bWVudCkpCgojY29tYmluZSAyIHNlcGFyYXRlIHBhcnRfYiBwYXltZW50cyB0byBvbmUKZGNpX2RhdGE8LWRjaV9kYXRhICU+JSAKICBtdXRhdGUocGFydF9iID0gcGFydF9iX3BoeXMgKyBwYXJ0X2JfZG1lKQoKI3NhdmUgdG8gUkRTIGZpbGUKZGNpX2RhdGFfd3M8LSBkY2lfZGF0YQpzYXZlUkRTKGRjaV9kYXRhX3dzLGZpbGU9IkRDSV9taWRjb3Vyc2UvZGF0YS9kY2lfZGF0YS5yZHMiKQoKYGBgCgpgYGB7cn0KbGlicmFyeShkcGx5cikKbGlicmFyeShnZ3Bsb3QyKQojIFN0ZXAgMQpncGw8LWRjaV9kYXRhX3dzICU+JSAKI1N0ZXAgMgpncm91cF9ieShtb2RhbGl0eSkgJT4lIAojU3RlcCAzCnN1bW1hcmlzZShtZWFuX3BheW1lbnRzPSBtZWFuKHBheW1lbnQpKSAlPiUgCiNTdGVwIDQKZ2dwbG90KGFlcyh4ID0gbW9kYWxpdHksIHkgPSBtZWFuX3BheW1lbnRzLCBmaWxsID0gbW9kYWxpdHkpKSArCiAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogICAgdGhlbWVfY2xhc3NpYygpICsKICAgIGxhYnMoCiAgICAgICAgeCA9ICJNb2RhbGl0eSIsCiAgICAgICAgeSA9ICJBdmVyYWdlIFBheW1lbnRzIiwKICAgICAgICB0aXRsZSA9ICJBdmVyYWdlIFBheW1lbnRzIHZzIE1vZGFsaXR5IgogICAgICAgICkgCgogICAgZ3BsKyBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscz1jKCJISCIgPSAiSG9tZSBIZW1vIiwgIkhJQyIgPSAiSGVtbyBJbi1DZW50ZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUEQiID0gIlBlcml0b25lYWwiKSkKCmBgYAogCmBgYHtyfQpkY2lfZGF0YSAlPiUgCiAgc2VsZWN0KHBheW1lbnQscGFydF9hLHBhcnRfYl9waHlzLHBhcnRfYl9kbWUscGFydF9iKQpgYGAKCgpgYGB7cn0KI3N1bShpcy5uYShkY2lfZGF0YSRjbGFpbV9sYXN0X2RpYWx5c2lzX2RhdGUpKQpzdW0oaXMubmEoZGNpX2RhdGEpKQpgYGAKIApgYGB7cn0Kc3RyKGRjaV9kYXRhKQpgYGAKCgpIaXN0b2dyYW1zIHRvIHVuZGVyc3RhbmQgdGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgZGF0YSBmb3IgcGF5bWVudHMKYGBge3J9CmRjaV9kYXRhX3dzICU+JSAKICBzZWxlY3QgKHBheW1lbnQscGFydF9hLHBhcnRfYl9waHlzLHBhcnRfYl9waHlzKSAlPiUgCiAgZ2dwbG90KGFlcyh4PXBheW1lbnQpICkrCiAgZ2VvbV9oaXN0b2dyYW0oY29sb3I9IiNlOWVjZWYiLCBhbHBoYT0wLjYsIHBvc2l0aW9uID0gJ2lkZW50aXR5JywgYmlucz00MCkgKwogIHNjYWxlX3hfbG9nMTAoKSsKc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWMoIiM2OWIzYTIiLCAiIzQwNDA4MCIpKSArCiBsYWJzKHg9ImxvZ2dnZWQgcGF5bWVudCB2YWx1ZXMiLAogICAgICB5PSJDb3VudHMiLAogICAgICB0aXRsZSA9ICJQYXltZW50IGRpc3RyaWJ1dGlvbiIpCmBgYAoKYGBge3J9CiNtYWtlIHRoaXMgaW50ZXJhY3RpdmUKcDwtIGdncGxvdChkY2lfZGF0YV93cyxhZXMoeD1wYXltZW50LHk9Li5kZW5zaXR5Li4pKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlucz00MCxiaW53aWR0aCA9IDAuMDUsZmlsbCA9ICJibGFjayIsY29sb3I9ImJsYWNrIixhbHBoYT0wLjIpICsKICBzY2FsZV94X2xvZzEwKCkrCmdlb21fZGVuc2l0eShjb2xvciA9ICJyZWQiKSsKIGxhYnMoeD0iTG9nZ2VkIHBheW1lbnRzIiwKICAgICAgeT0iRnJlcXVlbmN5IiwKICAgICAgdGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIHRvdGFsIHBheW1lbnRzIikKZ2dwbG90bHkocCkKCgoKYGBgCmBgYHtyfQojbWFrZSB0aGlzIGludGVyYWN0aXZlCgpwbHRfbW9kPC1kY2lfZGF0YV93cyAlPiUgCiAgICAgICAgICBmaWx0ZXIoZG9zX21vbnRoID09IDYsZG9zX3llYXI9PTIwMTcpICU+JSAKICAgICAgICAgIGdncGxvdChhZXMoeD1wYXltZW50LGZpbGw9bW9kYWxpdHkpKSArCiAgICAgICAgICBnZW9tX2hpc3RvZ3JhbShiaW5zPTEwLGJpbndpZHRoID0gMC4yNSxhbHBoYT0wLjgscG9zaXRpb24gPSAiZG9kZ2UiKSArCiAgICAgICAgICBzY2FsZV94X2xvZzEwKCkrCiAgICAgICAgICBsYWJzKHg9ImxvZ2dnZWQgcGF5bWVudCB2YWx1ZXMiLAogICAgICAgICAgeT0iRnJlcXVlbmN5IiwKICAgICAgICAgICB0aXRsZSA9ICJQYXltZW50IGRpc3RyaWJ1dGlvbiIpCnBsdF9tb2QKCmBgYApNb2RhbGl0eSBkaXN0cmlidXRpb25zCmBgYHtyfQojZGVuc2l0eSBkaXN0cmlidXRpb24gZm9yIG1vZGFsaXRpZXMKZ2dwbG90KGRjaV9kYXRhX3dzLGFlcyhwYXltZW50LCBjb2xvciA9IG1vZGFsaXR5LGZpbGw9bW9kYWxpdHkpKSArCiAgc2NhbGVfeF9sb2cxMCgpKwogIGdlb21fZGVuc2l0eShhbHBoYSA9IDAuOCxwb3NpdGlvbiA9ICJkb2RnZSIpICsKICBsYWJzKHg9IlBheW1lbnRzIiwKICAgICAgIHk9IkRlbnNpdHkiLAogICAgICAgdGl0bGU9IkRpc3RyaWJ1dGlvbiBvbiBwYXltZW50cyBieSBtb2RhbGl0eSIpCmBgYApgYGB7cn0KZGNpX2RhdGFfd3MgJT4lIAogIHNlbGVjdChwYXltZW50LG1vZGFsaXR5KSAlPiUgCiAgZ3JvdXBfYnkobW9kYWxpdHkpICU+JSAKICBzdW1tYXJpc2UodG90YWxfcGF5bWVudHM9c3VtKHBheW1lbnQpLG51bV9vZl9yb3dzPW4oKSkKYGBgCmBgYHtyfQojRnVuY3Rpb24gdG8gY3JlYXRlIGFuIGhpc3RncmFtIGZvciBlYWNoIGtpbmQgb2YgbWFkYWxpdHkgSElDLEhIIEFORCBQRAptYWtlX3Bsb3QgPC0gZnVuY3Rpb24obW9kKXsKICBkY2lfZGF0YV93cyAlPiUgCiAgc2VsZWN0KHBheW1lbnQsbW9kYWxpdHkpICU+JSAKICBmaWx0ZXIobW9kYWxpdHkgPT0gbW9kKSAlPiUgCiAgIGdncGxvdChhZXMoeD1wYXltZW50KSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpdGg9MTAwMCkgKwogIHNjYWxlX3hfbG9nMTAoKSArCiAgbGFicyh4PSJwYXltZW50cyIsCiAgICAgICB5PSJmcmVxdWVuY3kiLAogICAgICAgdGl0bGUgPSBwYXN0ZSgiRGlzdHJpYnV0aW9uIG9mIixtb2QpKQp9Cm1ha2VfcGxvdCgnSEgnKQptYWtlX3Bsb3QoJ0hJQycpCm1ha2VfcGxvdCgnUEQnKQoKYGBgCgpgYGB7cn0KZGNpX2RhdGFfd3MgJT4lIAogIHNlbGVjdChwYXltZW50LG1vZGFsaXR5KSAlPiUgCiAgZmlsdGVyKG1vZGFsaXR5ID09ICdISCcpICU+JSAKICAgZ2dwbG90KGFlcyh4PXBheW1lbnQpKSArCiAgZ2VvbV9oaXN0b2dyYW0oKSArCiAgbGFicyh4PSJwYXltZW50cyIsCiAgICAgICB5PSJmcmVxdWVuY3kiLAogICAgICAgdGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIEhlbW8gSG9tZSBQYXltZW50cyIpCiAKYGBgCmBgYHtyfQpkY2lfZGF0YV93cyAlPiUgCnNlbGVjdChwYXltZW50LG1vZGFsaXR5KSAlPiUgCiNmaWx0ZXIocGF5bWVudD4yODAwICYgcGF5bWVudCA8MzUwMCkgJT4lIAogIGdyb3VwX2J5KG1vZGFsaXR5KSAKICAKCgoKYGBgCmBgYHtyfQpkY2lfZGF0YV93cyAlPiUgCiAgc2VsZWN0KHBheW1lbnQsbW9kYWxpdHkpICU+JSAKICBmaWx0ZXIocGF5bWVudD4yODAwICYgcGF5bWVudCA8MzUwMCkgJT4lIAogICNncm91cF9ieShtb2RhbGl0eSkgJT4lIAogIGZpbHRlcihtb2RhbGl0eT09J1BEJykgJT4lIAogIGdncGxvdChhZXMoeD1wYXltZW50KSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gNDAwMCkKYGBgCgpgYGB7cn0KZGNpX2RhdGFfd3MgJT4lIAogIHNlbGVjdChwYXltZW50LG1vZGFsaXR5KSAlPiUgCiAgZmlsdGVyKHBheW1lbnQ+MjgwMCAmIHBheW1lbnQgPDM1MDApIApgYGAKCgpgYGB7cn0KbGlicmFyeShyZXNoYXBlMikKZGNpX2xvbmcgPC0gcmVzaGFwZTI6Om1lbHQoZGNpX2RhdGFfd3MpCmdncGxvdChkY2lfbG9uZywgYWVzKHZhbHVlKSkgKyBmYWNldF93cmFwKH52YXJpYWJsZSwgc2NhbGVzID0gJ2ZyZWVfeCcpICsKICBnZW9tX2hpc3RvZ3JhbSgpCiAgCgpgYGAKCmBgYHtyfQojZkN1bW11bGF0aXZlIGZyZXF1ZW5jeSBkaXN0cmlidXRpb24gd2l0aCBkZW5zaXR5IGxpbmVzCiN4PC0gc2FtcGxlKDA6MzAsIDIwMCwgcmVwbGFjZT1ULCBwcm9iPTE1IC0gYWJzKDE1IC0gMDozMCkpCng8LWRjaV9kYXRhX3dzJHBheW1lbnQKIyMgQ2FsY3VsYXRlIGFuZCBwbG90IHRoZSB0d28gaGlzdG9ncmFtcwpoY3VtIDwtIGggPC0gaGlzdCh4LCBwbG90PUZBTFNFKQpoY3VtJGNvdW50cyA8LSBjdW1zdW0oaGN1bSRjb3VudHMpCnBsb3QoaGN1bSwgbWFpbj0iIikKcGxvdChoLCBhZGQ9VCwgY29sPSJncmV5IikKCiMjIFBsb3QgdGhlIGRlbnNpdHkgYW5kIGN1bXVsYXRpdmUgZGVuc2l0eQpkIDwtIGRlbnNpdHkoeCkKbGluZXMoeCA9IGQkeCwgeSA9IGQkeSAqIGxlbmd0aCh4KSAqIGRpZmYoaCRicmVha3MpWzFdLCBsd2QgPSAyKQpsaW5lcyh4ID0gZCR4LCB5ID0gY3Vtc3VtKGQkeSkvbWF4KGN1bXN1bShkJHkpKSAqIGxlbmd0aCh4KSwgbHdkID0gMikKYGBgCgpgYGB7cn0KI2Rpc3RyaWJ1dGlvbiBieSBwYXltZW50IHR5cGUKIHBheW1lbnRfdHlwZV9kaXN0PC1kY2lfZGF0YV93cyAlPiUgCiAgICAgICAgICAgICAgICAgICAgICBzZWxlY3QoZG9zX3llYXIsZG9zX21vbnRoLHBheW1lbnQscGFydF9hLHBhcnRfYixpbnBhdGllbnQsb3V0cGF0aWVudF9kaWFseXNpcyklPiUgCiAgICAgICAgICAgICAgICAgICAgICAgcGl2b3RfbG9uZ2VyKHBheW1lbnQ6b3V0cGF0aWVudF9kaWFseXNpcyxuYW1lc190bz0icGF5bWVudF90eXBlIix2YWx1ZXNfdG8gPSAicGF5bWVudCIpIAoKc2F2ZVJEUyhwYXltZW50X3R5cGVfZGlzdCxmaWxlPSJEQ0lfbWlkY291cnNlL2RhdGEvcGF5bWVudF90eXBlX2Rpc3QucmRzIikKYGBgCmBgYHtyfQojZmF0IHRhaWxlZCBkaXMuIApib3hfcGw8LXBheW1lbnRfdHlwZV9kaXN0ICU+JSAKICBmaWx0ZXIoZG9zX3llYXIgPT0gMjAxNyAmIGRvc19tb250aCA9PSAxKSAlPiUgCiAgZ2dwbG90KGFlcyh5ID0gcGF5bWVudCx4ID0gcGF5bWVudF90eXBlLGZpbGw9cGF5bWVudF90eXBlKSkgKwogIGdlb21fYm94cGxvdCgpKwogICMgIHNjYWxlX3lfbG9nMTAoKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICBsYWJzKHg9IlBheW1lbnQgdHlwZSIsIHkgPSAiUGF5bWVudCIsCiAgICAgICB0aXRsZSA9ICJQYXltZW50IGRpc3RyaWJ1dGlvbiBieSBwYXltZW50IHR5cGVzIikKIApnZ3Bsb3RseShib3hfcGwpCmBgYAoKCgpgYGB7cn0KI3Bsb3QgdGhlIGZlcXVlbmN5IGRpc3RyaWJ1dGlvbiBhY3Jvc3MgZGlmZmVyZW50IHBheW1lbnQgdHlwZXMKICAKICBwbDwtZGNpX2RhdGFfd3MgJT4lIAogICAgICAgIHNlbGVjdChkb3NfeWVhcixkb3NfbW9udGgsbG9jYXRpb25faWQscGF5bWVudCxpbnBhdGllbnQsb3V0cGF0aWVudF9kaWFseXNpcyklPiUgCiAgICAgICAgcGl2b3RfbG9uZ2VyKHBheW1lbnQ6b3V0cGF0aWVudF9kaWFseXNpcyxuYW1lc190bz0icGF5bWVudF90eXBlIix2YWx1ZXNfdG8gPSAicGF5bWVudCIpICU+JSAKICAgICAgICBmaWx0ZXIoZG9zX3llYXI9PTIwMTcgJiBkb3NfbW9udGg9PTEpICU+JSAKICAgICAgICBnZ3Bsb3QoIGFlcyh4PXBheW1lbnQsZmlsbD1wYXltZW50X3R5cGUsY29sb3I9IHBheW1lbnRfdHlwZSkpICsKICAgICAgICBnZW9tX2hpc3RvZ3JhbShiaW5zPSA0MCxiaW53aWR0aCA9IDAuMDUsYWxwaGE9MC41LHBvc2l0aW9uID0gImlkZW50aXR5IikgKwogICAgICAgIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMCwxMzAwMDAsNTAwMCkpICsKICAgICAgICBzY2FsZV94X2xvZzEwKCkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKHBheW1lbnQsbmEucm09VCkpLGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsc2l6ZSA9IDEpICsKICBsYWJzKHg9IkxvZ2dlZCBwYXltZW50cyIseT0iRnJlcXVlbmN5Iix0aXRsZSA9ICJQYXltZW50czogSW5wYXRpZW50L0hvc3BpdGFsaXphdGlvbiBvciBPdXRwYXRpZW50IikgCiAgICAgICAgCiBwbAoKYGBgCiAKYGBge3J9CnN1bShpcy5uYShkY2lfZGF0YSRwYXltZW50KSkKYGBgCgoKCgogCmBgYHtyfQoKeWVhcnNfcGxvdDwtIGRjaV9kYXRhX3dzICU+JSAKICBncm91cF9ieShkb3NfeWVhcixkb3NfbW9udGgpICU+JSAKICBzdW1tYXJpc2Uoc3VtX3BheSA9IHN1bShwYXltZW50KSkgJT4lIAogIHVuZ3JvdXAoKSAgCgpwbCA8LSBnZ3Bsb3QoIHllYXJzX3Bsb3QsYWVzKHk9c3VtX3BheSwgeCA9IGRvc19tb250aCAsZmlsbD1kb3NfeWVhcikpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5Iixwb3NpdGlvbiA9ICdkb2RnZScpICsKICBsYWJzKHg9Ik1vbnRocyIsIHk9ICJQYXltZW50cyIpICsKICBnZ3RpdGxlKCJUb3RhbCBwYXltZW50cyBpbmNyZWFzZSBpbiBlYWNoIG1vbnRoIikKICAgICAgIApwbAp5ZWFyc19wbG90CiAgCmBgYAoKYGBge3J9CmdncGxvdGx5KGRjaV9kYXRhX3dzICU+JSAKICBncm91cF9ieShtb2RhbGl0eSxkb3NfbW9udGgsZG9zX3llYXIpICU+JSAKICBzdW1tYXJpc2UocGF5bWVudHMgPSBzdW0ocGF5bWVudCkpICU+JSAgCiAgdW5ncm91cCgpICU+JSAKICMgZ2dwbG90KGFlcyh4PW1vZGFsaXR5LHk9cGF5bWVudHMsZmlsbCA9IGBkb3NfeWVhcmApKSArCiAgICAgZ2dwbG90KGFlcyh4PWRvc19tb250aCx5PXBheW1lbnRzLGZpbGwgPSBgbW9kYWxpdHlgKSkgKwogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5Iixwb3NpdGlvbj0iZG9kZ2UiICkgKQogCgpgYGAKYGBge3J9CiNzaG93IGhvdyBtb2RhbGl0aWVzIGFyZSBkb2luZyBieSB0b3RhbCBwYXltZW50cyAKbW9kYWxpdHlfcGw8LWRjaV9kYXRhX3dzICU+JSAKICBncm91cF9ieShkb3NfeWVhcixtb2RhbGl0eSkgJT4lIAogIHN1bW1hcmlzZShwYXltZW50cyA9IHN1bShwYXltZW50KSkgJT4lIAp1bmdyb3VwKCkgJT4lIAogIGdncGxvdChhZXMoeD1kb3NfeWVhcix5PXBheW1lbnRzLGZpbGw9bW9kYWxpdHksY29sb3I9bW9kYWxpdHkpKSsKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIscG9zaXRpb249ImRvZGdlIikgKwogICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQocGF5bWVudHMpLHZqdXN0PTApLHBvc3Rpb249cG9zaXRpb25fZG9kZ2Uod2lkdGg9NSkpICsKbGFicyh4PSJNb2RhbGl0aWVzIGluIDIwMTcgYW5kIDIwMTgiLHk9InBheW1lbnRzIix0aXRsZT0iUGF5bWVudHMgYnkgbW9kYWxpdHkiKQoKbW9kYWxpdHlfcGwKYGBgCmBgYHtyfQpkY2lfZGF0YV93cyAgJT4lIAogIGdncGxvdChhZXMoeD1kb3NfeWVhcix5PXBheW1lbnQsY29sb3IgPSBtb2RhbGl0eSkpICsKICAgIGdlb21fYm94cGxvdCgpICsKICBzY2FsZV95X2xvZzEwKCkgKwogIGxhYnMoeCA9ICJZZWFycyIseT0icGF5bWVudHMiLCAKICAgICAgIHRpdGxlID0gIlBheW1lbnRzIGluIGluIDIwMTcgYW5kIDIwMTgiKQoKYGBgCmBgYHtyfQojVG9wIDUwIG1vc3QgZXhwZW5zaXZlIHBhdGllbnRzIApUb3A1MF9leHBlbnNpdmVfcGF0aWVudHM8LWhlYWQoYXJyYW5nZShkY2lfZGF0YV93cyxkZXNjKHBheW1lbnQpKSwgbiA9IDUwKQoKcGx0XzUwPC1Ub3A1MF9leHBlbnNpdmVfcGF0aWVudHMgJT4lIAogICNtdXRhdGUoZXhwX3BhdGllbnQgPSBtYXgocGF5bWVudCkpICU+JSAKICBnZ3Bsb3QoYWVzKHk9cGF5bWVudCx4PXBhdGllbnRfaWQsIGZpbGw9bW9kYWxpdHkpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIgKSArCiAgdGhlbWVfYncoKSsKICBsYWJzKHg9IlBhdGllbnQgSUQncyIsCiAgICAgICB5PSJQYXltZW50cyIsCiAgICAgICB0aXRsZT0iNTAgZXhwZW5zaXZlIHBhdGllbnRzIikKCnBsdF81MCAgKyB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBoanVzdCA9IDEpKQpgYGAKUGVyY2VudGFnZSBiYXJzCmBgYHtyfQpsaWJyYXJ5KHBsb3RseSkKc2V0LnNlZWQoMTIzKQoKZGYgPC0gZGNpX2RhdGFfd3MgJT4lIAogIHNlbGVjdChwYXltZW50LGlucGF0aWVudCxvdXRwYXRpZW50X2RpYWx5c2lzLG1vZGFsaXR5KSAlPiUgCiAgcGl2b3RfbG9uZ2VyKGlucGF0aWVudDpvdXRwYXRpZW50X2RpYWx5c2lzLG5hbWVzX3RvID0gImhvc3BpdGFsaXphdGlvbiIsdmFsdWVzX3RvID0gInBheW1lbnRzIikKCnAgPC0gZ2dwbG90KGRmLCBhZXMoeCA9IG1vZGFsaXR5KSkgKyAKICBnZW9tX2JhcihhZXMoeSA9IC4uY291bnQuLi9zdW0oLi5jb3VudC4uKSwgZmlsbCA9IGhvc3BpdGFsaXphdGlvbikpICsgCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJTZXQzIikgKyAKICB5bGFiKCJQZXJjZW50IikgKyAKICBnZ3RpdGxlKCJTaG93IHByZWNlbnRhZ2VzIGluIGJhciBjaGFydCIpCgpwIDwtIGdncGxvdGx5KHApCgpwCgpgYGAKCgpgYGB7cn0KZGNpX2RhdGFfd3MgJT4lIAogICAgc2VsZWN0KHBheW1lbnQsaW5wYXRpZW50LG91dHBhdGllbnRfZGlhbHlzaXMsbW9kYWxpdHkpICU+JSAKICBncm91cF9ieShtb2RhbGl0eSkgJT4lIAogIHN1bW1hcmlzZShwYXltZW50PXN1bShwYXltZW50KSwgaW5wYXRpZW50PXN1bShpbnBhdGllbnQpLG91dHBhdGllbnQ9c3VtKG91dHBhdGllbnRfZGlhbHlzaXMpKSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBwaXZvdF9sb25nZXIoaW5wYXRpZW50Om91dHBhdGllbnQsbmFtZXNfdG8gPSAicGF5VHlwZSIsdmFsdWVzX3RvID0gInBheXMiKSAgJT4lIAogIGdncGxvdChhZXMoeD1tb2RhbGl0eSx5PXBheW1lbnQsZmlsbD1wYXlUeXBlKSkrCiAgICAgICAgICAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLHBvc2l0aW9uPSJzdGFjayIpCgpgYGAKCmBgYHtyfQpvdGhlcl9jb2x1bW5zIDwtIGMoInBheW1lbnQiLCJob3NwaXRhbF9lcGlzb2RlcyIsImVyX3Zpc2l0cyIsImNhcmRpbyIsIm9waW9pZHMiLCJhbnRpZGlhYmV0aWNzIiwiYmV0YV9ibG9ja2VycyIsImFudGloeXBlcnRlbnNpdmVzIiwic25mX2Rpc2NoYXJnZSIpCmNvcnJzX290aGVycyA8LSBkY2lfZGF0YV93cyAlPiUgc2VsZWN0KG90aGVyX2NvbHVtbnMpICU+JSAKICBjb3IoKQpjb3Jyc19vdGhlcnMKCiMgQ2hhbmdlIGJhY2tncm91bmQgY29sb3IgdG8gbGlnaHRibHVlCmNvcnJwbG90KGNvcnJzX290aGVycywgdHlwZSA9ICJ1cHBlciIsIG9yZGVyID0gImhjbHVzdCIsCiAgICAgICAgIGNvbCA9IGMoImJsYWNrIiwgIndoaXRlIiksIGJnID0gImxpZ2h0Ymx1ZSIpCmBgYApgYGB7cn0KaGVhZChkY2lfZGF0YV93cykKYGBgCmBgYHtyfQojYXNrIG1pY2hhZWwgYWJvdXQgaG93IHRvIHBsb3QgdGhpcwpkY2lfZGF0YV93c1ssNjozNl0gJT4lIAogIHNlbGVjdCgtcGFydF9hLC1wYXJ0X2JfcGh5cywtb3V0cGF0aWVudF9vdGhlciwtcGFydF9iX2RtZSwtaW5wYXRpZW50LC1vdXRwYXRpZW50X2RpYWx5c2lzLC1vdXRwYXRpZW50X2VyLC1zbmYsLXZhc2NfYWNjZXNzLC1lcG9fcHJvdG9jb2xfZmxhZywtaXJvbl9wcm90b2NvbF9mbGFnLC1udXRzdXBfcHJvdG9jb2xfZmxhZywtc3VwX25hbWUsLXR4LC10eF9lcG8pCiAgCmBgYApjb3JyZWxhdGlvbmFsIHBsb3QKYGBge3J9Cm51bV9jb2x1bW5zIDwtIGMoImhnYiIsInRzYXQiLCJmZXJyIiwiYWxidW1pbiIsInB0aCIsImNhIiwiY2NhIiwicGgiLCJrIiwidXJyIiwia3R2IikKY29ycnM8LWRjaV9kYXRhX3dzICU+JSBzZWxlY3QobnVtX2NvbHVtbnMpICU+JSAKICMgZHJvcF9uYV8oKSAlPiUgCiAgY29yKCkKY29ycnMKYGBgCgoKCgpgYGB7cn0KbnVtX2NvbHVtbnMgPC0gYygicGF5bWVudCIsImhnYiIsInRzYXQiLCJmZXJyIiwiYWxidW1pbiIsInB0aCIsImNhIiwiY2NhIiwicGgiLCJrIiwidXJyIiwia3R2IikKY29ycnM8LWRjaV9kYXRhX3dzICU+JSBzZWxlY3QobnVtX2NvbHVtbnMpICAlPiUgCmNvcigpCgoKY29ycnBsb3QoY29ycnMsdHlwZSA9ICJ1cHBlciIsb3JkZXIgPSAiaGNsdXN0IiwKICAgICAgICAgdGwuY29sPSJibGFjayIsdGwuc3J0PTQ1KQogIAogCmBgYAoKCmBgYHtyfQp0aWJibGUoJ3ZhcmlhYmxlJyA9IGNvcnJzWzEsMjoxMl0gJT4lIG5hbWVzKCksJ2NvcnJlbGF0aW9uJyA9IGNvcnJzWzEsMjoxMl0pICU+JSAKICBnZ3Bsb3QoYWVzKHg9cmVvcmRlcih2YXJpYWJsZSxjb3JyZWxhdGlvbikseSA9IGNvcnJlbGF0aW9uKSkgKwogIGdlb21fcG9pbnQoKSsKICBnZW9tX3NlZ21lbnQoYWVzKHhlbmQ9dmFyaWFibGUseWVuZD0wKSkrCiAgY29vcmRfZmxpcCgpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwKSArCiAgbGFicyh4ID0iTGFicyIsCiAgICAgICB5ID0iQ29ycmVsYXRpb24iLAogICAgICAgdGl0bGUgPSAiQ29ycmVsYXRpb24gYmV0d2VlbiBMYWIgdmFsdWVzIGFuZCBQYXltZW50cyIpCmBgYAoKCmBgYHtyfQpwbCA8LSBnZ3Bsb3QoZGNpX2RhdGFfd3MsIGFlcyh4PWFsYnVtaW4seT1wYXltZW50KSApICsKICBnZW9tX3BvaW50KGFscGhhPTAuMikgKyBnZW9tX3Ntb290aChtZXRob2QgPSAnbG0nKSArCiAgc2NhbGVfeF9sb2cxMCgpICsKICBzY2FsZV95X2xvZzEwKCkKCmdncGxvdGx5KHBsKQpgYGAKYGBge3J9CiN1bmlxdWUoZGNpX2RhdGFfd3Mka3R2KQojaGdiIHZzIHBheW1lbnQKCmdncGxvdChkY2lfZGF0YV93cywgYWVzKHg9aGdiLHk9cGF5bWVudCkgKSArCiAgZ2VvbV9wb2ludCgpICsgZ2VvbV9zbW9vdGgobWV0aG9kID0gJ2xtJykgKwogIHNjYWxlX3hfbG9nMTAoKSArCiAgbGFicyh4PSJoZ2IiLCB5ID0gInBheW1lbnQiLCB0aXRsZSA9ICJQYXltZW50IFZzIGhnYiIpCgoKYGBgCmBgYHtyfQoKZ2dwbG90KGRjaV9kYXRhX3dzLCBhZXMoeD1jYSx5PXBheW1lbnQpICkgKwogIGdlb21fcG9pbnQoKSArIGdlb21fc21vb3RoKG1ldGhvZCA9ICdsbScpICsKICBzY2FsZV94X2xvZzEwKCkgKwogIGxhYnMoeD0iY2EiLCB5ID0gInBheW1lbnQiLCB0aXRsZSA9ICJQYXltZW50IFZzIGNhIikKCmBgYApNYXBzCmBgYHtyfQojZmlyc3QgcHJlcCB0aGUgZGF0YXNldCB0byBnZXQgdGhlIGluZm9ybWF0aW9uIG9uIHRoZSBtYXAgbWFya2VycwoKIHBheW1lbnRfc3VtbWFyeV9ieV9sb2M8LWRjaV9kYXRhX3dzICU+JSAKICBzZWxlY3QocGF0aWVudF9pZCxsb2NhdGlvbl9pZCxkb3NfbW9udGgsZG9zX3llYXIscGF5bWVudCxwYXJ0X2EscGFydF9iX3BoeXMscGFydF9iX2RtZSxtb2RhbGl0eSkgJT4lIAogIGdyb3VwX2J5KGxvY2F0aW9uX2lkLGRvc19tb250aCxkb3NfeWVhciApICU+JSAKICBzdW1tYXJpc2UoCiAgICAgICAgICAgIHRvdGFsX3BhdGllbnRzID0gTlJPVyhwYXRpZW50X2lkKSwKICAgICAgICAgICAgdG90YWxwYXltZW50cyA9IHJvdW5kKHN1bShwYXltZW50KSxkaWdpdHM9MiksCiAgICAgICAgICAgIG1pbl9wYXkgPSBtaW4ocGF5bWVudCksCiAgICAgICAgICAgIG1heF9wYXkgPSBtYXgocGF5bWVudCksCiAgICAgICAgICAgIGF2Z19wYXkgPSBzdW0ocGF5bWVudCkvTlJPVyhwYXRpZW50X2lkKSkgJT4lIAogIHVuZ3JvdXAoKSAlPiUKICBhcnJhbmdlKGRvc195ZWFyLGRvc19tb250aCkgIAoKI21lcmdlIHRoZSBncm91cGVkIGRhdGEgd2l0aCBsb2NhdGlvbiBkYXRhc2V0CnBheW1lbnRfZ2VvbV9zdW1tYXJ5IDwtIG1lcmdlKHBheW1lbnRfc3VtbWFyeV9ieV9sb2MsbG9jYXRpb25zLGJ5ID0gImxvY2F0aW9uX2lkIikKCnBheW1lbnRfZ2VvbV9zdW1tYXJ5ICU+JQogIGZpbHRlcihsb2NhdGlvbl9pZCA9PScwMDAwNTUnICYgZG9zX21vbnRoID09MSAmIGRvc195ZWFyID09MjAxNykKICAKI3NhdmUgaXQgdG8gcmRzIGZpbGUKc2F2ZVJEUyhwYXltZW50X2dlb21fc3VtbWFyeSwgZmlsZSA9ICJEQ0lfbWlkY291cnNlL2RhdGEvcGF5bWVudF9nZW9tX3N1bW1hcnkucmRzIikKCiAKYGBgCmBgYHtyfQpwYXltZW50X2dlb21fc3VtbWFyeSAlPiUgCiAgYXJyYW5nZShkZXNjKHRvdGFscGF5bWVudHMpKSAlPiUgCiAgZmlsdGVyKGRvc195ZWFyPT0yMDE3ICYgZG9zX21vbnRoID09IDEpCgpgYGAKCmBgYHtyfQojVG9wIDUgbG9jYXRpb25zIHdpdGggaGlnaCBhdmVyYWdlIHBheW1lbnRzCgpsb2NfcGx0PC1wYXltZW50X3N1bW1hcnlfYnlfbG9jICU+JSAKICBhcnJhbmdlKGRlc2ModG90YWxwYXltZW50cykpICU+JSAKICBmaWx0ZXIoZG9zX3llYXI9PTIwMTcgJiBkb3NfbW9udGggPT0gNCkgJT4lIAogIHRvcF9uKDUpICU+JSAKICBnZ3Bsb3QoYWVzKHg9bG9jYXRpb25faWQseT1hdmdfcGF5KSkgKwogIGdlb21fY29sKCApCgpnZ3Bsb3RseShsb2NfcGx0KQoKCmBgYAoKYGBge3J9CmxlYWZsZXQoZGF0YT0gbG9jYXRpb25zKSAlPiUgCiAgYWRkVGlsZXMoKSAlPiUgCiAgYWRkTWFya2Vycyh+bG9uZ2l0dWRlLAogICAgICAgICAgICAgfmxhdGl0dWRlLAogICAgICAgICAgICAgcG9wdXAgPSAoImhlbGxvIikpCmBgYApgYGB7cn0KcGwgPC0gZ2dwbG90KGRjaV9kYXRhX3dzLCBhZXMoeD1hbGJ1bWluLHk9cGF5bWVudCkgKSArCiAgZ2VvbV9wb2ludChhbHBoYT0wLjIpICsgZ2VvbV9zbW9vdGgobWV0aG9kID0gJ2xtJykgKwogIHNjYWxlX3hfbG9nMTAoKSArCiAgc2NhbGVfeV9sb2cxMCgpCgpnZ3Bsb3RseShwbCkKYGBgCgpgYGB7cn0KZGNpX2RhdGFfd3MgJT4lIAogIHNlbGVjdChkb3NfeWVhcixkb3NfbW9udGgscGF5bWVudCxwYXJ0X2EscGFydF9iKSAlPiUgCiAgICBmaWx0ZXIoZG9zX3llYXI9PTIwMTcsZG9zX21vbnRoPT0xKSAlPiUgCiAgcGl2b3RfbG9uZ2VyKHBhcnRfYTpwYXJ0X2IsbmFtZXNfdG8gPSAicGF5VHlwZSIsdmFsdWVzX3RvID0gInBheW1lbnRzIikgJT4lIAogIGdncGxvdChhZXMoeD1wYXlUeXBlLHk9cGF5bWVudHMsZmlsbD1wYXltZW50cykpKwogICAgICAgICAgIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5Iixwb3NpdGlvbj0iZG9kZ2UiKSsKICBsYWJzKHg9IlBheW1lbnQgVHlwZXMiLAogICAgICAgeT0iUGF5bWVudHMiLAogICAgICAgdGl0bGUgPSAiUGF5bWVudHMgIGJ5IFBheW1lbnQgdHlwZXMiKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCgpgYGAKCmBgYHtyfQojUGF5bWVudHMgYnkgTW9kYWxpdGllcwoKc2hvd19wbG90PC1kY2lfZGF0YV93cyAlPiUgCiAgICAgICAgICAgICAgIHNlbGVjdChkb3NfeWVhcixkb3NfbW9udGgscGF5bWVudCxwYXJ0X2EscGFydF9iLG1vZGFsaXR5KSAlPiUgCiAgICAgICAgICAgICAgZmlsdGVyKGRvc195ZWFyPT0yMDE4LGRvc19tb250aD09MSkgJT4lIAogICAgICAgICAgICAgIGdncGxvdChhZXMoeD1tb2RhbGl0eSx5PXBheW1lbnQsZmlsbD1wYXltZW50KSkrCiAgICAgICAgICAgICAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLHBvc2l0aW9uPSJkb2RnZSIsYWxwaGE9MC4zKSsKICAgICAgICAgICAgICBsYWJzKHg9Ik1vZGFsaXRpZXMiLAogICAgICAgICAgICAgIHk9IlBheW1lbnRzIiwKICAgICAgICAgICAgICB0aXRsZSA9ICJQYXltZW50cyAgYnkgTW9kYWxpdGllcyIpCnNob3dfcGxvdCArIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzPWMoIkhIIiA9ICJIb21lIEhlbW8iLCAiSElDIiA9ICJIZW1vIEluLUNlbnRlciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJQRCIgPSAiUGVyaXRvbmVhbCIpKQpgYGAKCmBgYHtyfQpkY2lfZGF0YV93cyAlPiUgCiAgc2VsZWN0KGRvc195ZWFyLGRvc19tb250aCxwYXltZW50LHBhcnRfYSxwYXJ0X2IpICU+JSAKICBtdXRhdGUocGVyY2VudF9wYXJ0X2EgPSByb3VuZChwYXJ0X2EvcGF5bWVudCoxMDApKSAlPiUgCiAgZmlsdGVyKGRvc195ZWFyPT0yMDE3LGRvc19tb250aD09MSkKCmBgYAoKYGBge3J9CmRjaV9kYXRhX3NoaW55ICU+JSAKICBzZWxlY3QgKGxvY2F0aW9uX2lkLHBhdGllbnRfaWQscGF5bWVudCxwYXJ0X2EscGFydF9iLG1vZGFsaXR5KQoKYGBgCgoK